Java Academy · leksjon

Future og feilhåndtering

Bruk Future.get med tidsavbrudd, håndter ExecutionException og avbryt kjørende oppgaver.

Leksjon 3 av 413 trinn

Future og feilhåndtering er en gratis leksjon i Java Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Java Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Java Academy inneholder totalt 4 leksjoner.

Hva er Future?

En Future<V> representerer resultatet som fortsatt ventes på fra en asynkron beregning. Den tilbyr metoder for å kontrollere om beregningen er fullført, vente på resultatet og håndtere feil.

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 tidsavbrudd

Foretrekk alltid varianten med tidsavbrudd for å unngå at kjøringen blir hengende 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 oppgaven kastet et unntak, pakker future.get() det inn i ExecutionException. Pakk det ut 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
}

Avbryte en Future

cancel(mayInterruptIfRunning) forsøker å avbryte oppgaven. Metoden returnerer true hvis avbrytningen lykkes. Hvis mayInterruptIfRunning er true, sendes et interrupt-signal til tråden som kjører.

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 kontra isDone

isDone() returnerer true hvis oppgaven ble fullført normalt, kastet et unntak eller ble avbrutt. isCancelled() returnerer true bare hvis oppgaven ble avbrutt.

// 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 for resultater som blir tilgjengelige først

ExecutorCompletionService pakker inn en pool og tilbyr en take()-metode for å hente den neste fullførte Future-en (i fullføringsrekkefølge, ikke innsendingsrekkefølge):

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());
}

Trygg håndtering av flere Futures

Ved innsamling av resultater fra mange futures bør De iterere gjennom dem og håndtere unntak 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() etter avslutning av poolen

Innsending etter shutdown() kaster RejectedExecutionException. Futures som ble sendt inn FØR avslutningen, kan likevel hentes etter at poolen er avsluttet:

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: Manuell Future

FutureTask<V> implementerer både Runnable og Future<V> — nyttig når De trenger en Future uten en ExecutorService:

FutureTask<String> task = new FutureTask<>(() -> "computed");
new Thread(task).start(); // run in any thread
System.out.println(task.get()); // computed

Nytt forsøk-mønster med Future

Implementer enkel logikk for nye forsøk rundt 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
    }
}

Begrensninger ved Future

java.util.concurrent.Future har begrensninger:

  • Ingen tilbakekallingsfunksjoner — De må blokkere med get()
  • Kan ikke lenke sammen transformasjoner
  • Kan ikke kombinere flere futures

Bruk CompletableFuture (i neste kurs) for reaktiv, ikke-blokkerende komposisjon.

Kort kontrollspørsmål

En oppgave kaster et unntak. Hvilket unntak kastes når De kaller future.get()?

Oppsummering: Future og feilhåndtering

Viktig å huske:

  • future.get() blokkerer; bruk alltid varianten med tidsavbrudd
  • ExecutionException pakker inn unntak fra oppgaven; pakk dem ut med getCause()
  • cancel(true) sender et interrupt-signal; isDone/isCancelled brukes til å kontrollere status
  • ExecutorCompletionService.take() henter futures i fullføringsrekkefølge
  • FutureTask implementerer både Runnable og Future
Gratis å komme i gang

Lær deg Java med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
104
Leksjoner
374

Ofte stilte spørsmål

Er leksjonen «Future og feilhåndtering» gratis?

Ja – hele teksten i «Future og feilhåndtering» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Java Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Java Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Future og feilhåndtering»?

Bruk Future.get med tidsavbrudd, håndter ExecutionException og avbryt kjørende oppgaver. Du øver på Java Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Java Academy?

Ingen tidligere erfaring er nødvendig. Java Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Future og feilhåndtering»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Java Academy-leksjonen?

Ja. Alle Java Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. ExecutorService og trådpooltyper
  2. Sende inn oppgaver: Runnable kontra Callable
  3. Future og feilhåndtering
  4. ScheduledExecutorService for gjentakende oppgaver
← Tilbake til Java Academy