Future og fejlhåndtering
Brug Future.get med timeouts, håndtér ExecutionException, og annullér kørende opgaver.
Future og fejlhåndtering er en gratis Java Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Java Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Java Academy-kurset indeholder 4 lektioner i alt.
Hvad er Future?
En Future<V> repræsenterer det afventende resultat af en asynkron beregning. Den indeholder metoder til at kontrollere, om beregningen er færdig, vente på resultatet og håndtere fejl.
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() med tidsudløb
Foretræk altid varianten med tidsudløb for at forhindre, at programmet hænger på ubestemt tid:
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
Hvis opgaven kastede en undtagelse, pakker future.get() den ind i ExecutionException. Pak den ud med getCause():
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
}Annullering af en Future
cancel(mayInterruptIfRunning) forsøger at annullere opgaven. Metoden returnerer true, hvis det lykkes. Hvis mayInterruptIfRunning er true, sendes en afbrydelse til den kørende tråd.
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 sammenlignet med isDone
isDone() returnerer true, hvis opgaven blev fuldført normalt, kastede en undtagelse eller blev annulleret. isCancelled() returnerer kun true, hvis opgaven blev annulleret.
// 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 til først tilgængelige resultater
ExecutorCompletionService pakker en pulje ind og indeholder en take()-metode til at hente den næste fuldførte Future (i rækkefølgen, de fuldføres, ikke i indsendelsesrækkefølgen):
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());
}Sikker håndtering af flere Futures
Når du samler resultater fra mange Futures, skal du gennemløbe dem og håndtere undtagelser for hver enkelt Future:
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() efter nedlukning af puljen
Indsendelse efter shutdown() kaster RejectedExecutionException. Futures, der blev indsendt FØR nedlukningen, kan dog stadig hentes efter nedlukningen:
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: Manuel Future
FutureTask<V> implementerer både Runnable og Future<V> — nyttig, når du har brug for en Future uden en ExecutorService:
FutureTask<String> task = new FutureTask<>(() -> "computed");
new Thread(task).start(); // run in any thread
System.out.println(task.get()); // computedGenforsøgsmønster med Future
Implementer enkel genforsøgslogik omkring future.get():
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
}
}Begrænsninger ved Future
java.util.concurrent.Future har begrænsninger:
- Ingen tilbagekald — du skal blokere med get()
- Kan ikke kæde transformationer
- Kan ikke kombinere flere Futures
Brug CompletableFuture (i næste kursus) til reaktiv, ikke-blokerende sammensætning.
Hurtigt tjek
En opgave kaster en undtagelse. Hvilken undtagelse kastes, når du kalder future.get()?
Opsummering: Future og fejlhåndtering
Vigtigste pointer:
- future.get() blokerer; brug altid varianten med tidsudløb
- ExecutionException pakker undtagelser fra opgaven ind; pak dem ud med getCause()
- cancel(true) sender en afbrydelse; brug isDone/isCancelled til status
- ExecutorCompletionService.take() henter Futures i den rækkefølge, de fuldføres
- FutureTask implementerer både Runnable og Future
Lær Java med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 104
- Lektioner
- 374
Ofte stillede spørgsmål
Er lektionen “Future og fejlhåndtering” gratis?
Ja — hele teksten til “Future og fejlhåndtering” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Java Academy-kurset, skal du opgradere til CoddyKit PRO. Java Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Future og fejlhåndtering”?
Brug Future.get med timeouts, håndtér ExecutionException, og annullér kørende opgaver. Du øver dig i Java Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Java Academy?
Der kræves ingen tidligere erfaring. Java Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Future og fejlhåndtering”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Java Academy-lektion?
Ja. Alle Java Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- ExecutorService og typer af thread pools
- Indsendelse af opgaver: Runnable vs. Callable
- Future og fejlhåndtering
- ScheduledExecutorService til gentagne opgaver