2012-07-21 122 views
0
System.out.println("Thread state: " + threads[i].getState()); 
threads[i].notify(); 

产生以下输出:Java - 无法通知等待线程?

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) 

这是怎么回事?为什么我不能通知睡眠线程?

编辑:

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

编辑:对于线程[]类的代码下面是调用此

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){} 
    } 
} 
+0

你可以显示正在等待的线程的代码吗? – 2012-07-21 04:48:50

+0

你想达到什么目的?通知'Thread'对象不会导致任何事情发生,除非有另一个线程调用'wait()'。 – SimonC 2012-07-21 04:57:40

+0

是的,我给你的状态输出在调用notify()之前,你看到它正在等待 – Trup 2012-07-21 05:01:29

回答

2

代码你打印出一个ballThreads[i]的状态,那么通知一个threads[i]。不确定这是否是预期行为,但是当您不拥有对象的显示器时,您不允许通知线程。你确定你在对象的synchronized()块内调用了这个吗?


编辑:

是,这段代码取出的方法是同步的

您的编辑你的问题后,​​是方法,而不是对象的监视器,您需要将代码放在如下所示的块中:

synchronized(threads[i]) { 
    // some stuff 
    threads[i].notify(); 
} 

这里的重要一点(与方法声明中的​​关键字相反)是您在一个对象上同步,然后在该块内部,您可以调用notify()对象对象。例子:

public void run() 
{ 
    synchronized(myObject) { 
     // do some stuff 
     myObject.notify(); 
    } 
} 

public void run() 
{ 
    synchronized(thread1) { 
     // do some stuff 
     thread1.notify(); 
    } 
} 

public void run() 
{ 
    synchronized(syncObject) { 
     // do some stuff 
     syncObject.notify(); 
    } 
} 

看到这个模式?此处更多信息:http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

+0

看到编辑,你没有在对象的监视器上同步 – 2012-07-21 05:00:47

+0

@Trup不,你正在同步一个方法,它使用对象实例作为监视器,而不是你调用notify()对象**你需要同步你调用'notify()'的对象的实例。 – 2012-07-21 05:07:16

+0

@Trup ok,这里有一堆例子 – 2012-07-21 05:12:43

1

wait()notifiy()要求您在等待的对象上进行同步。如果你用于锁定同步块相同的对象上做一个wait()notify(),那么你将摆脱非法监控状态异常

1

你是完全误解wait/notify机制的工作方式的。线程必须决定是否需要等待。然后该线程必须调用wait。然后,有什么事情发生。然后你拨打notify告诉线索发生了什么事。

如果没有首先确定应该等待的具体内容,则不能让线程调用wait。并且在线程需要被通知的事情已经发生之前,你不能调用notify。发生的事情应该是线程在决定等待时检查的内容。

您遇到错误的原因是与等待的事件关联的同步根本不存在,这违反了wait/notify的语义。

如果您在等待邮箱非空,则应检查邮箱是否为空,如果是,请拨打wait。确保您仍在邮箱的同步例程内,否则您无法知道邮箱(仍然)为空。然后,当您将信件放入邮箱(必须位于邮箱的同步例程内)时,请致电notify让任何等待的线程知道邮箱已更改状态。您必须等待以获得的线程可以测试的内容,例如邮箱的状态。