Ho ancora qualche dubbio sull'utilizzo dei thread purtroppo e vorrei chiarirmelo una volta per tutte.
Sto svolgendo un esercizio dove la traccia richiede di simulare una corsa tra alcuni corridori e non appena il primo arriva al traguardo il giudice (messo in attesa appena l'applicazione viene avviata) si risveglia e annuncia il vincitore.
Il mio problema però è che viene generata una IllegalMonitorException nel momento in cui cerco di risvegliare il giudice.
Questo è il codice:
package test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JOptionPane;
import dati.Corridori;
import dati.Giudice;
public class TestCorridori {
public static void main(String[] args) {
Corridori corridore = new Corridori();
Giudice giudice = new Giudice();
String numero = JOptionPane.showInputDialog("inserisci il numero di corridori");
int numeroCorridori = Integer.parseInt(numero);
Thread thread = new Thread(giudice, "GIUDICE");
thread.start();
creaCorridori(numeroCorridori, corridore, giudice);
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
Giudice.stampaClassifica();
}
public static void creaCorridori(int numero, Corridori corridore, Giudice giudice) {
List<Thread> lista = new ArrayList<Thread>(numero);
for(int i=0; i<numero; i++) {
String nome = JOptionPane.showInputDialog("inserisci il nome del " + (i+1) + "° corridore");
Thread thread = new Thread(corridore,nome);
lista.add(thread);
}
Iterator<Thread> iteratore = lista.iterator();
while(iteratore.hasNext()) {
iteratore.next().start();
}
}
}
package dati;
import java.util.ArrayList;
import java.util.List;
import dati.Corridori;
public class Giudice implements Runnable {
private static List<Thread> classifica = new ArrayList<Thread>();
private static boolean flag = false;
//Corridori corridori = new Corridori();
@Override
public synchronized void run() {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(flag == false) {
vincitore(Corridori.getThread().getName());
flag = true;
}
Giudice.creaClassifica(Corridori.getThread());
}
public static void vincitore(String corridore) {
System.out.println(corridore + " ha vinto");
}
public static void creaClassifica(Thread corridore) {
classifica.add(corridore);
}
public static synchronized void risvegliaGiudice(Giudice giudice) {
giudice.notify();
}
public Giudice getGiudice() {
return this;
}
public static void stampaClassifica() {
int i=1;
for(Thread thread : classifica) {
System.out.println(i + "°: " + thread.getName());
i++;
}
}
}
package dati;
public class Corridori implements Runnable {
Giudice giudice = new Giudice();
@Override
public void run() {
for(int i=1; i<=10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": " + (i*10) + "m");
}
System.out.println(Thread.currentThread().getName() + " arrivato");
Giudice.risvegliaGiudice(giudice.getGiudice());
Giudice.creaClassifica(Thread.currentThread());
}
public static Thread getThread() {
return Thread.currentThread();
}
}
l'eccezione IllegalMonitorStateException viene generata nel momento in cui invochiamo il metodo wait(), notify() o notifyAll() su un oggetto di cui non abbiamo il lock.
innanzitutto io ero convinto del fatto che invocando uno di quei metodi all'interno di un blocco sincronizzato automaticamente questo comporterebbe l'acquisizione del lock dell'oggetto che credo avvenga correttamente nel mio codice e precisamente nel metodo risvegliaGiudice().
Il problema forse deriva dal fatto che l'oggetto sul quale è invocato il metodo notify() non è lo stesso sul quale è invocato il metodo wait() anche se credevo di aver risolto con il metodo getGiudice().
Mi aiutate a capire dove sbaglio?