Java - 无法通知等待线程?

时间:2012-07-21 04:47:20

标签: java multithreading

System.out.println("Thread state: " + threads[i].getState());
threads[i].notify();

产生以下输出:

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)

发生了什么事?为什么我不能通知睡眠线程?

编辑:threads []类的代码:

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

3 个答案:

答案 0 :(得分:2)

您打印出ballThreads[i]的状态,然后通知threads[i]。不确定这是否是预期的行为,但是当您不拥有对象的监视器时,不允许您通知线程。您确定要在synchronized()对象的threads[i]块内调用此内容吗?


编辑:

  

是的,取消此代码的方法是同步的

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

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

此处的重要位(与方法声明中的synchronized关键字相对)是您在对象上进行同步,然后在此块内,在对象<上调用notify() / em>的。例子:

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

答案 1 :(得分:1)

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

答案 2 :(得分:1)

您完全误解了wait / notify机制的工作方式。线程必须决定它需要等待的东西。然后线程必须调用wait。那件事必须发生。然后你打电话给notify告诉线程发生了什么事。

如果没有首先确定存在应该等待的特定内容,则无法调用线程wait。而且,在发生线程需要通知的情况之前,您无法调用notify。发生的事情应该与线程在决定等待时检查的内容相同。

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

如果您正在等待邮箱非空,则应检查邮箱是否为空,如果是,请致电wait。确保您仍在邮箱的同步例程中,否则您无法知道邮箱是否(仍然)为空。然后,当您在邮箱中放入一个字母(必须在邮箱的同步例程中)时,您调用notify让任何等待的线程知道邮箱已更改状态。您必须等待线程可以测试的某些内容,例如邮箱的状态。