System.out.println("Thread state: " + threads[i].getState());
threads[i].notify();
Produces the following output:
Thread state: WAITING
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at MyPakc.An.run(An.java:49)
at java.lang.Thread.run(Thread.java:679)
What is going on? Why can I not notify a sleeping thread?
EDIT: The code for the threads[] class:
package Part2;
import java.util.List;
import javax.swing.JPanel;
class BThread extends Thread{
private boolean completedThisIter = false;
@Override
public synchronized void run() {
while (true) {
completedThisIter = false;
doStuff()
System.out.println("Completed iter");
completedThisIter = true;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public boolean getCompletedThisIter() {
return completedThisIter;
}
}
EDIT: Here is the code that calls this
public synchronized void run(){
// OTHER STUFF
for (int iter = 0; iter < 1212; ++iter){
System.out.println("Iter " + iter);
lastAssignedBallIndex = -1;
for (int i = 0; i < numThreads; i++) {
//System.out.println("Num " + numThreads + " " + i);
//ballThreads[i] = new BallThread(ballList.subList(lastAssignedBallIndex+1,lastAssignedBallIndex+numBallsPerThread),
// ballPanel);
//lastAssignedBallIndex += numBallsPerThread;
System.out.println("State " + ballThreads[i].getState());
if (ballThreads[i].getState() == Thread.State.NEW) {
ballThreads[i].start();
} else { //if (ballThreads[i].getState() == Thread.State.BLOCKED) {
System.out.println("Thread state: " + ballThreads[i].getState());
ballThreads[i].notify();
}
}
//try{
for (int i = 0; i < numThreads; i++) {
while (!ballThreads[i].getCompletedThisIter()) {
System.out.println("iter:" + iter + " ball:" + i + " " + ballThreads[i].getCompletedThisIter());
//wait(); // TODO elliminate polling here
}
}
System.out.println("Joined");
//}
// catch(InterruptedException ie){ie.printStackTrace();}
ballPanel.repaint();
notifyAll();
try{
Thread.sleep(2);
}
catch (InterruptedException ie){}
}
}
You’re printing out the state of a
ballThreads[i]then notifying athreads[i]. Not sure if this is intended behavior but you’re not allowed to notify a thread when you don’t own the object’s monitor. Are you sure you’re calling this inside asynchronized()block for thethreads[i]object?EDIT:
After your edit to your question, the
synchronizedis on the method, and not the monitor of the object, you need to put your code in a block that looks like this:The important bit here (as opposed to the
synchronizedkeyword in a method declaration) is that you synchronize on an Object, then inside this block, you callnotify()on the Object. Examples:or
or
See the pattern? More info here: http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html