Java Academy · Lektion

Future og fejlhåndtering

Brug Future.get med timeouts, håndtér ExecutionException, og annullér kørende opgaver.

Lektion 3 af 413 trin

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()); // true

isCancelled 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()); // false

CompletionService 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()); // computed

Genforsø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
Gratis at komme i gang

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

  1. ExecutorService og typer af thread pools
  2. Indsendelse af opgaver: Runnable vs. Callable
  3. Future og fejlhåndtering
  4. ScheduledExecutorService til gentagne opgaver
← Tilbage til Java Academy