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

3 回答 3

2

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


编辑:

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

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

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

这里重要的一点(与synchronized方法声明中的关键字相反)是您在 Object 上同步,然后在此块内notify()调用Object。例子:

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

于 2012-07-21T04:53:23.230 回答
1

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

于 2012-07-21T04:55:52.430 回答
1

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

wait如果没有首先确定它应该等待特定的东西,就不能进行线程调用。notify并且在需要通知线程的事情已经发生之前,您不能调用。发生的事情应该与线程决定等待时正在检查的事情相同。

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

如果您正在等待邮箱非空,那么您应该检查邮箱是否为空,如果是,请调用wait. 确保您仍在邮箱的同步例程中,否则您无法知道邮箱(仍然)是空的。然后,当您将一封信放入邮箱(必须在邮箱的同步例程中)时,您调用notify以让任何等待线程知道邮箱已更改状态。您必须等待线程可以测试的东西,例如邮箱的状态。

于 2012-07-21T05:22:44.890 回答