0Pricing
Java Academy · Lezione

ExecutorService e tipi di thread pool

Crei thread pool fissi, memorizzati nella cache, singoli e pianificati e comprenda quando utilizzare ciascun tipo.

ExecutorService e tipi di thread pool è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 1 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 i pool di thread?

Creare un nuovo Thread per ogni attività è costoso: la creazione e la distruzione dei thread comportano un sovraccarico. Un pool di thread riutilizza un insieme fisso di thread per eseguire molte attività, riducendo il sovraccarico e controllando il consumo di risorse.

import java.util.concurrent.*;

// Bad practice: new thread per task
new Thread(() -> System.out.println("task")).start();

// Better: reuse threads from a pool
ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(() -> System.out.println("task from pool"));
pool.shutdown();

newFixedThreadPool

Crea un pool con esattamente N thread. Le attività aggiuntive vengono accodate finché un thread non diventa disponibile. È adatto quando si conosce il livello di parallelismo desiderato.

ExecutorService pool = Executors.newFixedThreadPool(4);

for (int i = 0; i < 10; i++) {
    final int taskId = i;
    pool.submit(() -> {
        System.out.println("Task " + taskId + " on " + Thread.currentThread().getName());
    });
}

pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);

newCachedThreadPool

Crea thread su richiesta e riutilizza quelli inattivi. I thread inattivi per 60 secondi vengono terminati. È adatto per molte attività di breve durata, ma rischioso per attività di lunga durata o senza limite, perché può esaurire la memoria.

ExecutorService cached = Executors.newCachedThreadPool();

for (int i = 0; i < 100; i++) {
    cached.submit(() -> {
        // quick task
        double result = Math.sqrt(Math.random());
    });
}
cached.shutdown();

newSingleThreadExecutor

Un pool con esattamente un thread. Le attività vengono eseguite in sequenza, nell'ordine di sottomissione. È adatto per serializzare l'accesso a una risorsa condivisa.

ExecutorService single = Executors.newSingleThreadExecutor();

single.submit(() -> System.out.println("Task 1"));
single.submit(() -> System.out.println("Task 2"));
single.submit(() -> System.out.println("Task 3"));
// Always prints: Task 1, Task 2, Task 3 (sequential)
single.shutdown();

newScheduledThreadPool

Supporta attività pianificate e ricorrenti. Lo utilizzi per il polling, i tentativi e la manutenzione in background.

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);

// One-shot delay
scheduler.schedule(() -> System.out.println("Delayed!"),
    3, TimeUnit.SECONDS);

// Fixed rate (every 2 seconds)
scheduler.scheduleAtFixedRate(
    () -> System.out.println("Tick"),
    0, 2, TimeUnit.SECONDS);

// Run later: scheduler.shutdown();

VirtualThreadExecutor (Java 21+)

Java 21 introduce i thread virtuali, leggeri ed economici da creare. Utilizzi Executors.newVirtualThreadPerTaskExecutor() per carichi di lavoro intensivi in termini di I/O:

// Java 21+
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) {
    for (int i = 0; i < 10_000; i++) {
        final int id = i;
        exec.submit(() -> {
            Thread.sleep(100); // blocks without tying up OS thread
            System.out.println("vthread " + id);
        });
    }
} // auto-shutdown

Scelta del pool appropriato

Linee guida:

  • Attività CPU-bound: pool fisso con N = numero di core della CPU
  • Attività I/O-bound: pool cached o thread virtuali
  • Attività sequenziali: executor a thread singolo
  • Attività pianificate o ricorrenti: pool di thread pianificato
int cores = Runtime.getRuntime().availableProcessors();
ExecutorService cpuPool = Executors.newFixedThreadPool(cores);
System.out.println("Pool size: " + cores);

ThreadPoolExecutor personalizzato

Per un controllo dettagliato, crei direttamente un ThreadPoolExecutor:

ThreadPoolExecutor tpe = new ThreadPoolExecutor(
    2,           // corePoolSize
    10,          // maximumPoolSize
    60L,         // keepAliveTime
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(100), // work queue
    Executors.defaultThreadFactory(),
    new ThreadPoolExecutor.CallerRunsPolicy() // rejection policy
);
tpe.submit(() -> System.out.println("Custom pool task"));
tpe.shutdown();

Arresto controllato

Arresti sempre ExecutorService per rilasciare i thread. shutdown() smette di accettare nuove attività, ma completa quelle accodate. shutdownNow() tenta di annullare le attività in esecuzione.

ExecutorService pool = Executors.newFixedThreadPool(4);
// ... submit tasks ...

pool.shutdown(); // no new tasks
try {
    if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
        pool.shutdownNow(); // force cancel
    }
} catch (InterruptedException e) {
    pool.shutdownNow();
    Thread.currentThread().interrupt();
}

ExecutorService come AutoCloseable (Java 19+)

In Java 19+, ExecutorService implementa AutoCloseable. Utilizzi try-with-resources per arrestarlo automaticamente:

// Java 19+ (preview), Java 21 stable
try (ExecutorService pool = Executors.newFixedThreadPool(4)) {
    pool.submit(() -> System.out.println("task"));
} // pool.close() called: waits for tasks then shuts down

Politiche di rifiuto

Quando il pool è saturo, cioè tutti i thread sono occupati e la coda è piena, la politica di rifiuto gestisce l'eccedenza:

  • AbortPolicy (predefinita): genera RejectedExecutionException
  • CallerRunsPolicy: il thread chiamante esegue l'attività
  • DiscardPolicy: elimina silenziosamente l'attività
  • DiscardOldestPolicy: elimina l'attività più vecchia nella coda

Controllo rapido

Dispone di un'attività CPU-bound che esegue calcoli pesanti. Quanti thread dovrebbe contenere il pool fisso?

Riepilogo: ExecutorService e pool di thread

Punti chiave:

  • Pool fisso: N thread fissi; le attività aggiuntive vengono accodate
  • Pool cached: cresce su richiesta; i thread inattivi scadono dopo 60 secondi
  • Thread singolo: l'ordine di esecuzione sequenziale è garantito
  • Pool pianificato: attività ritardate e ricorrenti
  • Chiami sempre shutdown(); utilizzi awaitTermination() per un'uscita controllata

Domande Frequenti

La lezione «ExecutorService e tipi di thread pool» è gratuita?

Sì — il testo completo di «ExecutorService e tipi di thread pool» è 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 «ExecutorService e tipi di thread pool»?

Crei thread pool fissi, memorizzati nella cache, singoli e pianificati e comprenda quando utilizzare ciascun tipo. 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 1 di 4.

Quanto tempo richiede la lezione «ExecutorService e tipi di thread pool»?

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