Esercizi Multithreading e Concorrenza in Java
Ecco degli esercizi con soluzione per praticare l’uso del multithreading e della concorrenza in Java.
Esercizio 1: Creazione di un Thread
Creare e avviare un thread estendendo la classe `Thread`.
public class ThreadEsteso extends Thread { public void run() { System.out.println("Esecuzione del thread: " + Thread.currentThread().getName()); }
public static void main(String[] args) { ThreadEsteso thread = new ThreadEsteso(); thread.start(); }}
Runnable
Esercizio 2: Implementazione di Creare e avviare un thread implementando l'interfaccia `Runnable`.
public class ThreadRunnable implements Runnable { public void run() { System.out.println("Esecuzione del thread: " + Thread.currentThread().getName()); }
public static void main(String[] args) { Thread thread = new Thread(new ThreadRunnable()); thread.start(); }}
Esercizio 3: Sincronizzazione di un Blocco di Codice
Utilizzare la parola chiave `synchronized` per sincronizzare un metodo in una classe che implementa `Runnable`.
public class Sincronizzazione implements Runnable { private int contatore = 0;
public synchronized void incrementa() { contatore++; System.out.println("Contatore: " + contatore); }
public void run() { for (int i = 0; i < 5; i++) { incrementa(); } }
public static void main(String[] args) { Sincronizzazione obj = new Sincronizzazione(); Thread t1 = new Thread(obj); Thread t2 = new Thread(obj); t1.start(); t2.start(); }}
Callable
e Future
Esercizio 4: Uso di Creare un task utilizzando `Callable` e recuperare il risultato utilizzando `Future`.
import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;
public class CallableEsempio { public static void main(String[] args) { ExecutorService executor = Executors.newSingleThreadExecutor(); Callable<Integer> task = () -> { Thread.sleep(1000); return 123; };
Future<Integer> future = executor.submit(task);
try { Integer result = future.get(); System.out.println("Risultato: " + result); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } finally { executor.shutdown(); } }}
CountDownLatch
Esercizio 5: Utilizzo di Utilizzare `CountDownLatch` per sincronizzare l'esecuzione di più thread.
import java.util.concurrent.CountDownLatch;
public class CountDownLatchEsempio { public static void main(String[] args) { CountDownLatch latch = new CountDownLatch(3);
Runnable task = () -> { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + " completato"); latch.countDown(); } catch (InterruptedException e) { e.printStackTrace(); } };
for (int i = 0; i < 3; i++) { new Thread(task).start(); }
try { latch.await(); System.out.println("Tutti i thread sono completati"); } catch (InterruptedException e) { e.printStackTrace(); } }}
ScheduledExecutorService
Esercizio 6: Esecuzione Periodica con Utilizzare `ScheduledExecutorService` per eseguire un task periodicamente.
import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;
public class ScheduledTask { public static void main(String[] args) { ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = () -> { System.out.println("Esecuzione del task: " + Thread.currentThread().getName()); };
scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
// Eseguire il task periodico per 5 secondi prima di spegnere il scheduler try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } finally { scheduler.shutdown(); } }}