Ce face Future.cancel
cancel încearcă să anuleze sarcina din spatele unui Future. Dacă sarcina stă încă la coadă, nu mai pornește deloc. Dacă rulează deja, parametrul decide: cu true firul ei este întrerupt (primește InterruptedException în sleep, wait etc.), cu false este lăsată să se termine.
cancel returnează false dacă sarcina s-a terminat deja sau a fost deja anulată. După o anulare reușită, isCancelled() și isDone() sunt true, iar get() aruncă CancellationException.
Întreruperea este o cerere, nu o oprire forțată: o sarcină care doar calculează fără să verifice Thread.interrupted() continuă să ruleze.
Parametri
| Parametru | Descriere |
|---|---|
intrerupeDacaRuleaza |
true ca să întrerupă firul care rulează deja sarcina; false ca doar să o împiedice să pornească. |
Ce returnează
true dacă anularea a reușit, false dacă sarcina era deja terminată sau anulată.
Exemple
Exemplul 1: Anularea unei descărcări lungi
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) throws Exception {
try (ExecutorService executor = Executors.newSingleThreadExecutor()) {
Future<String> descarcare = executor.submit(() -> {
Thread.sleep(10_000);
return "film.mp4";
});
Thread.sleep(100);
System.out.println("Anulare reușită: " + descarcare.cancel(true));
System.out.println("isCancelled: " + descarcare.isCancelled() + ", isDone: " + descarcare.isDone());
System.out.println("A doua anulare: " + descarcare.cancel(true));
try {
descarcare.get();
} catch (CancellationException e) {
System.out.println("get() aruncă CancellationException");
}
}
}
}
Rezultat
Anulare reușită: true
isCancelled: true, isDone: true
A doua anulare: false
get() aruncă CancellationException
Exemplul 2: O sarcină terminată nu se mai poate anula
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) throws Exception {
try (ExecutorService executor = Executors.newSingleThreadExecutor()) {
Future<Integer> suma = executor.submit(() -> 150 + 250);
System.out.println("Rezultat: " + suma.get());
System.out.println("cancel după terminare: " + suma.cancel(true));
System.out.println("isCancelled: " + suma.isCancelled());
}
}
}
Rezultat
Rezultat: 400
cancel după terminare: false
isCancelled: false
Exemplul 3: Sarcina care nu a pornit încă
Executorul are un singur fir, ocupat cu prima sarcină. A doua stă la coadă și este anulată înainte să pornească, deci mesajul ei nu apare.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Main {
public static void main(String[] args) throws Exception {
try (ExecutorService executor = Executors.newSingleThreadExecutor()) {
Future<?> prima = executor.submit(() -> {
Thread.sleep(300);
System.out.println("Prima sarcină s-a terminat");
return null;
});
Future<?> aDoua = executor.submit(() -> System.out.println("A doua sarcină a rulat"));
System.out.println("Anulez a doua: " + aDoua.cancel(false));
prima.get();
}
}
}
Rezultat
Anulez a doua: true
Prima sarcină s-a terminat
Greșeli frecvente
- Crezi că
cancel(true)oprește orice cod. Oprește doar codul care reacționează la întrerupere (sleep,wait, I/O întreruptibil sau verificăriThread.interrupted()). - Apelezi
get()dupăcancelfără să prinziCancellationException.
Comenzi înrudite
Future: Rezultatul unei sarcini care rulează pe alt fir: get() așteaptă și îl returnează, isDone() spune dacă s-a terminat.ExecutorService.submit: Trimite o sarcină executorului și returnează imediat un Future din care iei mai târziu rezultatul.Executors.newScheduledThreadPool: Creează un executor care rulează sarcini după o întârziere sau periodic (la fiecare N secunde).