Ce face Executors.newScheduledThreadPool
newScheduledThreadPool(n) returnează un ScheduledExecutorService: un executor care poate programa sarcini în timp. Este înlocuitorul modern al clasei vechi Timer.
schedule(sarcina, 2, TimeUnit.SECONDS) rulează sarcina o dată, după 2 secunde. scheduleAtFixedRate o rulează periodic, la intervale fixe măsurate de la începutul fiecărei rulări. scheduleWithFixedDelay lasă o pauză fixă între sfârșitul unei rulări și începutul următoarei.
Sarcinile periodice nu se opresc singure: le oprești cu cancel pe ScheduledFuture primit sau cu shutdown() pe executor. Dacă o rulare aruncă o excepție, următoarele rulări nu mai au loc.
Parametri
| Parametru | Descriere |
|---|---|
nFire |
Câte fire păstrează executorul pentru sarcinile programate. |
intarziere |
După cât timp rulează sarcina. |
perioada / pauza |
Intervalul dintre rulări, pentru sarcinile periodice. |
unitate |
Unitatea de timp (TimeUnit.MILLISECONDS, SECONDS…). |
Ce returnează
Un ScheduledExecutorService. Metodele schedule… returnează un ScheduledFuture.
Exemple
Exemplul 1: Mementouri cu întârzieri diferite
Sarcinile sunt trimise în altă ordine, dar rulează în ordinea întârzierilor.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorService ceas = Executors.newScheduledThreadPool(1);
ceas.schedule(() -> System.out.println("300 ms: Pleacă trenul spre Brașov"), 300, TimeUnit.MILLISECONDS);
ceas.schedule(() -> System.out.println("100 ms: Ia biletul"), 100, TimeUnit.MILLISECONDS);
ceas.schedule(() -> System.out.println("200 ms: Mergi la peronul 3"), 200, TimeUnit.MILLISECONDS);
ceas.shutdown();
ceas.awaitTermination(2, TimeUnit.SECONDS);
System.out.println("Toate mementourile au rulat");
}
}
Rezultat
100 ms: Ia biletul
200 ms: Mergi la peronul 3
300 ms: Pleacă trenul spre Brașov
Toate mementourile au rulat
Exemplul 2: O verificare periodică, oprită după 3 rulări
Sarcina rulează la fiecare 100 ms. Un CountDownLatch așteaptă trei rulări, apoi sarcina este anulată.
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorService ceas = Executors.newScheduledThreadPool(1);
AtomicInteger nr = new AtomicInteger();
CountDownLatch treiRulari = new CountDownLatch(3);
ScheduledFuture<?> verificare = ceas.scheduleAtFixedRate(() -> {
if (nr.get() < 3) {
System.out.println("Verific stocul, rularea " + nr.incrementAndGet());
treiRulari.countDown();
}
}, 0, 100, TimeUnit.MILLISECONDS);
treiRulari.await();
verificare.cancel(false);
ceas.shutdown();
System.out.println("Anulată: " + verificare.isCancelled());
}
}
Rezultat
Verific stocul, rularea 1
Verific stocul, rularea 2
Verific stocul, rularea 3
Anulată: true
Greșeli frecvente
- Lași o excepție să iasă din sarcina periodică. Executorul oprește în liniște toate rulările următoare. Prinde excepțiile în interiorul sarcinii.
- Uiți
shutdown(). Firul executorului ține programul pornit la nesfârșit. - Folosești
scheduleAtFixedRatepentru o sarcină care durează mai mult decât perioada. Rulările nu se suprapun, ci se adună întârziere după întârziere; foloseștescheduleWithFixedDelay.
Comenzi înrudite
Executors: Clasa cu metode statice care creează executori: cu număr fix de fire, cu un singur fir, cu fire virtuale sau programate.ExecutorService: Un grup de fire de execuție care primește sarcini și le rulează; se oprește cu shutdown() și se așteaptă cu awaitTermination().TimeUnit: Enumerarea unităților de timp (SECONDS, MINUTES…) folosită la așteptări; face conversii și pauze ușor de citit.CountDownLatch: Un numărător pentru așteptare: await() blochează până când alte fire apelează countDown() de N ori.Future.cancel: Anulează o sarcină: dacă nu a pornit, nu mai rulează; dacă rulează, o poate întrerupe.