[Thread] IllegalMonitorStateException

Gente alguém poderia dar um mamão com threads !?
Qual o problema com desse programa ???


public class TesteConsumer extends Thread {
	private static final Work no_work = new Work();
	private WorkQueue queue;
	private int workerNumber;
	public TesteConsumer(WorkQueue queue2, int i) {
		queue = queue2;
		workerNumber = i;
	}

	public TesteConsumer() {
	}

	public void run() {
		while (true){
			Object object = null;
			try {
				object = queue.getWork();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if (object == no_work) {
				notify();
				break;
			}
			System.out.println(object + " worker number " + workerNumber);
		}
	}
	public static void main(String[] args) {
		TesteConsumer consumer = new TesteConsumer();
		consumer.execute();
	}
	
	private synchronized void execute() {
		WorkQueue queue = new WorkQueue();
		
		for (int i = 0; i < 10; i++) {
			TesteConsumer consumer = new TesteConsumer(queue, i);
			consumer.start();
		}
		
		for (int i = 0; i < 1000; i++) {
			Work work = new Work(i, i);
			queue.addWork(work);
		}
		
		for (int i = 0; i < 10; i++) {
			//Work work = new Work(i, i);
			queue.addWork(no_work);
		}
		while (!queue.queue.isEmpty()){
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

}
import java.util.LinkedList;

public class WorkQueue {
        LinkedList queue = new LinkedList();
    
        // Add work to the work queue
        public synchronized void addWork(Object o) {
            queue.addLast(o);
            notify();
        }
    
        // Retrieve work from the work queue; block if the queue is empty
        public synchronized Object getWork() throws InterruptedException {
            while (queue.isEmpty()) {
                wait();
            }
            return queue.removeFirst();
        }
    }
public class Work {
	
	public Work(int p, int q) {
		x = p;
		y = q;
	}
	public Work() {
	}
	int x;
	int y;
	
	public String toString() {
		return "x = " + x + " y = " + y; 
	}
}
(...)
x = 997 y = 997 worker number 1
x = 998 y = 998 worker number 0
x = 999 y = 999 worker number 3
java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.notify(Native Method)
	at TesteConsumer.run(TesteConsumer.java:23)
java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.notify(Native Method)
	at TesteConsumer.run(TesteConsumer.java:23)
java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.notify(Native Method)
	at TesteConsumer.run(TesteConsumer.java:23)
java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.notify(Native Method)
	at TesteConsumer.run(TesteConsumer.java:23)
(...)

Você não pode chamar wait, notify ou notifyAll se não possui a lock para o objeto.

Como assim ???

Como eu faço para a Thread principal do programa esperar o trabalhadores terminarem o serviço??? Como os trabalhadores podem notificar a Thread principal que seu serviço terminou ???

Seguinte:

Object  o =new Object();
o.notify();

Vai lançar IllegalMonitorStateException

Object  o =new Object();
synchronized(o) {
    o.notify();
}

Não vai.

Entende isso primeiro, depois como wait/notify e synchronized interagem entre sí e por fim resolve seu problema.

Mmm… isso significa que eu não posso sair assim notificando os threads! :roll:

Minha solução foi passar o employer (Thead principal) para os trabalhadores via construtor. Ai eu usei o syncronized (employer) { employer.notify()};
e tudo passou a funcionar.
:smiley:


Comentário: Em Perl, por exemplo, existem milhões de formas de resolver um mesmo problema. Muitas vezes o que a gente não sabe, é (qual) a maneira adequada para resolver um problema. Não imaginei que não fosse possível resolver sem usar syncronized(object) porque em vários lugares dizia-se que isto tem o mesmo efeito de utilizar o modificar syncronized no método.