Future ja virheenkäsittely
Käytä Future.get-metodia aikakatkaisujen kanssa, käsittele ExecutionException ja peruuta käynnissä olevia tehtäviä.
Future ja virheenkäsittely on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.
Mikä on Future?
Future<V> edustaa asynkronisen laskennan odottavaa tulosta. Se tarjoaa metodeja valmistumisen tarkistamiseen, tuloksen odottamiseen ja virheiden käsittelyyn.
import java.util.concurrent.*;
ExecutorService pool = Executors.newFixedThreadPool(2);
Future<Integer> future = pool.submit(() -> {
Thread.sleep(1000);
return 42;
});
System.out.println("Is done? " + future.isDone()); // false
Integer result = future.get(); // blocks
System.out.println("Result: " + result); // 42
pool.shutdown();future.get() aikakatkaisulla
Käyttäkää aina mieluummin aikakatkaisullista versiota, jotta suoritus ei jää odottamaan loputtomasti:
try {
Integer result = future.get(5, TimeUnit.SECONDS);
System.out.println(result);
} catch (TimeoutException e) {
System.out.println("Timed out");
future.cancel(true); // interrupt the task
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
System.out.println("Task threw: " + e.getCause());
}ExecutionException
Jos tehtävä heitti poikkeuksen, future.get() käärii sen ExecutionException-poikkeukseen. Purkakaa kääre getCause()-metodilla:
Future<String> failing = pool.submit(() -> {
throw new IllegalArgumentException("bad input");
});
try {
failing.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
System.out.println(cause.getClass().getSimpleName()); // IllegalArgumentException
System.out.println(cause.getMessage()); // bad input
}Futuren peruuttaminen
cancel(mayInterruptIfRunning) yrittää peruuttaa tehtävän. Se palauttaa arvon true, jos peruutus onnistui. Jos mayInterruptIfRunning on true, käynnissä olevalle säikeelle lähetetään keskeytys.
Future<String> f = pool.submit(() -> {
try {
Thread.sleep(10_000); // long task
return "done";
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return "interrupted";
}
});
boolean cancelled = f.cancel(true); // send interrupt
System.out.println("Cancelled: " + cancelled); // true
System.out.println("Is cancelled: " + f.isCancelled()); // trueisCancelled ja isDone
isDone() palauttaa arvon true, jos tehtävä valmistui normaalisti, heitti poikkeuksen tai peruutettiin. isCancelled() palauttaa arvon true vain, jos tehtävä peruutettiin.
// After cancel:
System.out.println(f.isDone()); // true
System.out.println(f.isCancelled()); // true
// After normal completion:
Future<Integer> done = pool.submit(() -> 5);
done.get(); // wait
System.out.println(done.isDone()); // true
System.out.println(done.isCancelled()); // falseCompletionService ensimmäisenä valmistuville tuloksille
ExecutorCompletionService käärii poolin ja tarjoaa take()-metodin seuraavan valmistuneen Futuren noutamiseen (valmistumisjärjestyksessä, ei lähetysjärjestyksessä):
ExecutorCompletionService<Integer> cs =
new ExecutorCompletionService<>(pool);
for (int i = 0; i < 5; i++) {
final int delay = 5 - i; // submit fastest last
cs.submit(() -> { Thread.sleep(delay * 100); return delay; });
}
for (int i = 0; i < 5; i++) {
Future<Integer> f = cs.take(); // next completed
System.out.println(f.get());
}Useiden Future-olioiden turvallinen käsittely
Kun keräätte tuloksia useista Future-olioista, käykää ne läpi ja käsitelkää poikkeukset kunkin Futuren kohdalla erikseen:
List<Future<String>> futures = new ArrayList<>();
for (int i = 0; i < 5; i++) {
final int id = i;
futures.add(pool.submit(() ->
id % 2 == 0 ? "ok_" + id : (() -> { throw new RuntimeException("fail_"+id); }).get()
));
}
for (Future<String> f : futures) {
try {
System.out.println(f.get());
} catch (ExecutionException e) {
System.out.println("Error: " + e.getCause().getMessage());
}
}Future.get() poolin sulkemisen jälkeen
Lähettäminen shutdown()-metodin kutsumisen jälkeen heittää RejectedExecutionException-poikkeuksen. Ennen sulkemista lähetettyjen Future-olioiden tulokset voidaan kuitenkin noutaa sulkemisen jälkeen:
ExecutorService pool2 = Executors.newFixedThreadPool(2);
Future<Integer> f = pool2.submit(() -> 99);
pool2.shutdown(); // no new tasks
// Still valid — task was submitted before shutdown:
System.out.println(f.get()); // 99
try {
pool2.submit(() -> 0); // throws!
} catch (RejectedExecutionException e) {
System.out.println("Pool shut down");
}FutureTask: manuaalinen Future
FutureTask<V> toteuttaa sekä Runnable- että Future<V>-rajapinnan — se on hyödyllinen, kun tarvitsette Futuren ilman ExecutorServiceä:
FutureTask<String> task = new FutureTask<>(() -> "computed");
new Thread(task).start(); // run in any thread
System.out.println(task.get()); // computedUudelleenyritysmalli Futuren avulla
Toteuttakaa yksinkertainen uudelleenyrityslogiikka future.get()-metodin ympärille:
Future<String> future = pool.submit(() -> {
if (Math.random() < 0.7) throw new RuntimeException("transient error");
return "success";
});
for (int attempt = 0; attempt < 3; attempt++) {
try {
System.out.println(future.get());
break;
} catch (ExecutionException e) {
System.out.println("Attempt " + (attempt+1) + " failed");
if (attempt == 2) throw e;
future = pool.submit(() -> "retry"); // resubmit
}
}Futuren rajoitukset
java.util.concurrent.Futurella on rajoituksia:
- Ei callback-funktioita — get()-metodi estää säikeen
- Muunnoksia ei voi ketjuttaa
- Useita Future-olioita ei voi yhdistää
Käyttäkää seuraavalla kurssilla käsiteltävää CompletableFuture-luokkaa reaktiiviseen, estämättömään koostamiseen.
Pikatarkistus
Tehtävä heittää poikkeuksen. Mikä poikkeus heitetään, kun kutsutte future.get()-metodia?
Kertaus: Future ja virheenkäsittely
Tärkeimmät asiat:
- future.get() estää säikeen; käyttäkää aina aikakatkaisullista versiota
- ExecutionException käärii tehtävien poikkeukset; purkakaa kääre getCause()-metodilla
- cancel(true) lähettää keskeytyksen; isDone/isCancelled ilmaisevat tilan
- ExecutorCompletionService.take() noutaa Future-oliot valmistumisjärjestyksessä
- FutureTask toteuttaa sekä Runnable- että Future-rajapinnan
Opi Java tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 104
- Oppitunnit
- 374
Usein kysytyt kysymykset
Onko oppitunti ”Future ja virheenkäsittely” ilmainen?
Kyllä – oppitunnin ”Future ja virheenkäsittely” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Future ja virheenkäsittely”?
Käytä Future.get-metodia aikakatkaisujen kanssa, käsittele ExecutionException ja peruuta käynnissä olevia tehtäviä. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.
Kuinka kauan ”Future ja virheenkäsittely”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?
Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- ExecutorService ja säiepoolityypit
- Tehtävien lähettäminen: Runnable ja Callable
- Future ja virheenkäsittely
- ScheduledExecutorService toistuviin tehtäviin