ScheduledExecutorService per attività ricorrenti
Pianifichi attività a intervalli fissi o con ritardi fissi per il polling e la manutenzione in background.
ScheduledExecutorService per attività ricorrenti è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 4 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.
Perché utilizzare ScheduledExecutorService?
ScheduledExecutorService estende ExecutorService per supportare la pianificazione delle attività. Sostituisce le classi legacy Timer/TimerTask con uno scheduler basato su un pool di thread e sicuro rispetto alle eccezioni.
import java.util.concurrent.*;
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
// One-shot delay
scheduler.schedule(
() -> System.out.println("Runs once after 3 seconds"),
3, TimeUnit.SECONDS
);
// Don't forget to shut down eventually:
// scheduler.shutdown();schedule: ritardo a esecuzione singola
schedule(task, delay, unit) esegue l'attività una volta trascorso il ritardo specificato. Funziona sia con Runnable sia con Callable:
ScheduledExecutorService s = Executors.newScheduledThreadPool(1);
// Runnable:
ScheduledFuture<?> sf1 = s.schedule(
() -> System.out.println("Runnable fired!"), 2, TimeUnit.SECONDS);
// Callable:
ScheduledFuture<Integer> sf2 = s.schedule(
() -> { System.out.println("Callable fired!"); return 42; },
2, TimeUnit.SECONDS);
System.out.println(sf2.get()); // 42 (after 2 seconds)scheduleAtFixedRate
scheduleAtFixedRate(task, initialDelay, period, unit) esegue ripetutamente l'attività a una frequenza fissa. Se un'attività richiede più tempo del periodo, l'esecuzione successiva inizia immediatamente dopo la sua conclusione, senza sovrapposizioni.
ScheduledExecutorService s = Executors.newScheduledThreadPool(1);
AtomicInteger count = new AtomicInteger();
ScheduledFuture<?> sf = s.scheduleAtFixedRate(
() -> System.out.println("Tick " + count.incrementAndGet()),
0, // initial delay
1, // period
TimeUnit.SECONDS
);
Thread.sleep(5000);
sf.cancel(false); // stop after 5 ticks
s.shutdown();scheduleWithFixedDelay
scheduleWithFixedDelay(task, initialDelay, delay, unit) attende il ritardo specificato DOPO il completamento di ogni attività, prima di avviare quella successiva. È adatto per il polling quando la durata dell'attività varia.
s.scheduleWithFixedDelay(
() -> {
System.out.println("Polling... " + Instant.now());
// variable-length polling task
},
0, // no initial delay
5, // 5-second gap AFTER each completion
TimeUnit.SECONDS
);
// Next execution = task end + 5 seconds (not task start)Frequenza fissa e ritardo fisso
La distinzione principale:
- scheduleAtFixedRate: prossimo avvio = ultimo avvio + periodo, con temporizzazione senza deriva
- scheduleWithFixedDelay: prossimo avvio = ultima conclusione + ritardo, con un intervallo garantito tra le esecuzioni
Utilizzi fixedRate per gli heartbeat e fixedDelay per il polling quando la durata dell'attività varia.
ScheduledFuture: annullamento
schedule/scheduleAtFixedRate/scheduleWithFixedDelay restituiscono un ScheduledFuture. Chiami cancel(false) per interrompere le esecuzioni future senza interrompere quella in corso:
ScheduledFuture<?> sf = scheduler.scheduleAtFixedRate(
() -> System.out.println("Heartbeat"), 0, 1, TimeUnit.SECONDS);
// Cancel after 5 seconds
scheduler.schedule(() -> sf.cancel(false), 5, TimeUnit.SECONDS);Gestione delle eccezioni nelle attività pianificate
Se un'attività pianificata genera un'eccezione non catturata, lo scheduler interrompe silenziosamente le esecuzioni ricorrenti: non ne verranno eseguite altre. La racchiuda sempre in un blocco try-catch:
scheduler.scheduleAtFixedRate(() -> {
try {
// risky work
if (Math.random() < 0.3) throw new RuntimeException("transient");
System.out.println("Success");
} catch (Exception e) {
System.err.println("Task error: " + e.getMessage());
// task continues to run on next interval
}
}, 0, 2, TimeUnit.SECONDS);Caso pratico: aggiornamento della cache
Utilizzi un'attività pianificata per aggiornare periodicamente una cache:
class PriceCache {
private volatile Map<String, Double> prices = new HashMap<>();
PriceCache(ScheduledExecutorService scheduler) {
scheduler.scheduleAtFixedRate(this::refresh, 0, 30, TimeUnit.SECONDS);
}
private void refresh() {
System.out.println("Refreshing prices...");
// prices = fetchFromDatabase();
}
Double getPrice(String symbol) { return prices.get(symbol); }
}Caso pratico: nuovo tentativo con backoff
Implementare un nuovo tentativo con exponential backoff usando attività pianificate:
void retryWithBackoff(Runnable task, int maxRetries, ScheduledExecutorService s) {
AtomicInteger attempts = new AtomicInteger(0);
long[] delay = {1}; // seconds
Runnable wrapper = new Runnable() {
public void run() {
try {
task.run();
} catch (Exception e) {
int n = attempts.incrementAndGet();
if (n < maxRetries) {
delay[0] *= 2;
s.schedule(this, delay[0], TimeUnit.SECONDS);
} else System.err.println("Max retries reached");
}
}
};
s.execute(wrapper);
}Monitoraggio: getDelay e getQueue
Esaminare lo stato dello scheduler:
ScheduledFuture<?> sf = scheduler.schedule(() -> {}, 10, TimeUnit.SECONDS);
System.out.println("Delay remaining: " + sf.getDelay(TimeUnit.SECONDS) + "s");
// ThreadPoolExecutor provides queue inspection:
if (scheduler instanceof ScheduledThreadPoolExecutor ste) {
System.out.println("Queue size: " + ste.getQueue().size());
}Arresto e svuotamento della coda
Durante l'arresto, decidere se le attività pianificate devono continuare a essere eseguite:
ScheduledThreadPoolExecutor ste = (ScheduledThreadPoolExecutor)
Executors.newScheduledThreadPool(2);
// Cancel scheduled tasks on shutdown (default: false = they run)
ste.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
ste.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
ste.shutdown();Verifica rapida
Un'attività pianificata con scheduleAtFixedRate(..., 1, TimeUnit.SECONDS) impiega 3 secondi per completarsi. Come gestisce questa situazione lo scheduler?
Riepilogo: ScheduledExecutorService
Punti chiave:
- schedule() — esecuzione singola con ritardo
- scheduleAtFixedRate() — temporizzazione senza deriva (da inizio a inizio)
- scheduleWithFixedDelay() — intervallo garantito (da fine a inizio)
- Le eccezioni non gestite interrompono silenziosamente le attività ricorrenti — racchiuderle sempre in un blocco try-catch
- Annullare con ScheduledFuture.cancel(false)
Domande Frequenti
La lezione «ScheduledExecutorService per attività ricorrenti» è gratuita?
Sì — il testo completo di «ScheduledExecutorService per attività ricorrenti» è 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 «ScheduledExecutorService per attività ricorrenti»?
Pianifichi attività a intervalli fissi o con ritardi fissi per il polling e la manutenzione in background. 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 4 di 4.
Quanto tempo richiede la lezione «ScheduledExecutorService per attività ricorrenti»?
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
- ExecutorService e tipi di thread pool
- Inviare attività: Runnable e Callable a confronto
- Future e gestione degli errori
- ScheduledExecutorService per attività ricorrenti