📢 Nuovo Corso Bootstrap Completo disponibile!

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();
}
}

Esercizio 2: Implementazione di Runnable

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();
}
}

Esercizio 4: Uso di Callable e Future

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();
}
}
}

Esercizio 5: Utilizzo di CountDownLatch

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();
}
}
}

Esercizio 6: Esecuzione Periodica con ScheduledExecutorService

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();
}
}
}