0Pricing
Java Academy · Lezione

Future e gestione degli errori

Utilizzi Future.get con timeout, gestisca ExecutionException e annulli le attività in esecuzione.

Future e gestione degli errori è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

Che cos'è Future?

Un Future<V> rappresenta il risultato ancora in sospeso di un calcolo asincrono. Fornisce metodi per verificare il completamento, attendere il risultato e gestire gli errori.

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() con timeout

Preferisca sempre la variante con timeout per evitare di rimanere bloccato indefinitamente:

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

Se l'attività ha generato un'eccezione, future.get() la racchiude in ExecutionException. La estragga con 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
}

Annullamento di un Future

cancel(mayInterruptIfRunning) tenta di annullare l'attività. Restituisce true se l'operazione riesce. Se mayInterruptIfRunning è true, al thread in esecuzione viene inviato un interrupt.

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

isDone() restituisce true se l'attività è stata completata normalmente, ha generato un'eccezione o è stata annullata. isCancelled() restituisce true solo se l'attività è stata annullata.

// 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 per i risultati disponibili per primi

ExecutorCompletionService racchiude un pool e fornisce un metodo take() per recuperare il Future completato successivo, in ordine di completamento e non di sottomissione:

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

Gestione sicura di più Future

Quando raccoglie i risultati di molti Future, li iteri e gestisca le eccezioni separatamente per ciascun 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() dopo l'arresto del pool

La sottomissione dopo shutdown() genera RejectedExecutionException. Tuttavia, i Future sottomessi PRIMA dell'arresto possono ancora essere recuperati dopo l'arresto:

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

FutureTask<V> implementa sia Runnable sia Future<V>: è utile quando è necessario un Future senza un ExecutorService:

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

Pattern di ritentativo con Future

Implementi una semplice logica di ritentativo attorno a 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
    }
}

Limitazioni di Future

java.util.concurrent.Future presenta alcune limitazioni:

  • Nessun callback: è necessario bloccarsi con get()
  • Non è possibile concatenare le trasformazioni
  • Non è possibile combinare più Future

Utilizzi CompletableFuture (nel corso successivo) per una composizione reattiva e non bloccante.

Controllo rapido

Un'attività genera un'eccezione. Quale eccezione viene generata quando chiama future.get()?

Riepilogo: Future e gestione degli errori

Punti chiave:

  • future.get() è bloccante; utilizzi sempre la variante con timeout
  • ExecutionException racchiude le eccezioni dell'attività; le estragga con getCause()
  • cancel(true) invia un interrupt; utilizzi isDone/isCancelled per verificare lo stato
  • ExecutorCompletionService.take() recupera i Future in ordine di completamento
  • FutureTask implementa sia Runnable sia Future

Domande Frequenti

La lezione «Future e gestione degli errori» è gratuita?

Sì — il testo completo di «Future e gestione degli errori» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Future e gestione degli errori»?

Utilizzi Future.get con timeout, gestisca ExecutionException e annulli le attività in esecuzione. Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «Future e gestione degli errori»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. ExecutorService e tipi di thread pool
  2. Inviare attività: Runnable e Callable a confronto
  3. Future e gestione degli errori
  4. ScheduledExecutorService per attività ricorrenti
← Torna a Java Academy