Java等待并通知:IllegalMonitorStateException
我不完全理解Java等待并通知:IllegalMonitorStateException,java,multithreading,concurrency,Java,Multithreading,Concurrency,我不完全理解等待和通知(关于对象)是如何工作的,因此我不得不将我的尝试缩减到以下代码部分 Main.java: import java.util.ArrayList; class Main { public static Main main = null; public static int numRunners = 4; public static ArrayList<Runner> runners = null; public static void mai
等待
和通知
(关于对象
)是如何工作的,因此我不得不将我的尝试缩减到以下代码部分
Main.java:
import java.util.ArrayList;
class Main
{
public static Main main = null;
public static int numRunners = 4;
public static ArrayList<Runner> runners = null;
public static void main(String[] args)
{
main = new Main();
}
Main()
{
runners = new ArrayList<Runner>(numRunners);
for (int i = 0; i < numRunners; i++)
{
Runner r = new Runner();
runners.add(r);
new Thread(r).start();
}
System.out.println("Runners ready.");
notifyAll();
}
}
当前,我在调用Main.Main.wait()时收到一个非法的MonitorStateException代码>,但我不明白为什么。从我看到的情况来看,我需要同步Runner.run
,但在这样做的时候,我假设它只会通知一个线程,而实际上是通知所有线程
我已经查看了java.util.concurrent
,但是我找不到合适的替代方法(可能我只是遗漏了什么)。您在不使用同步的块的情况下调用了等待和通知所有
。在这两种情况下,调用线程必须拥有调用方法的监视器上的锁
从notify
的文档中(wait
和notifyAll
有类似的文档,但请参阅notify
了解最完整的说明):
此方法只能由作为此对象监视器所有者的线程调用。线程通过以下三种方式之一成为对象监视器的所有者:
- 通过执行该对象的同步实例方法
- 通过在对象上执行同步的synchronized语句体
- 对于类类型的对象,执行该类的同步静态方法
一次只能有一个线程拥有对象的监视器
在notifyAll
之后,一次只有一个线程能够实际退出wait
,因为它们都必须再次获取相同的监视器-但是所有线程都将得到通知,因此,一旦第一个线程退出同步块,下一个线程将获取锁等。您不能wait()
在对象上,除非当前线程拥有该对象的监视器。要做到这一点,您必须对其进行同步
:
class Runner implements Runnable
{
public void run()
{
try
{
synchronized(Main.main) {
Main.main.wait();
}
} catch (InterruptedException e) {}
System.out.println("Runner away!");
}
}
同样的规则也适用于notify()
/notifyAll()
委员会提到:
此方法只能由作为此对象监视器所有者的线程调用。请参阅notify
方法,以了解线程成为监视器所有者的方式
抛出:
–如果当前线程不是此对象监视器的所有者
和来自:
线程在以下三种情况之一中成为对象监视器的所有者
方式:
- 通过执行该对象的同步实例方法
- 通过执行对象上同步的
synchronized
语句体
- 对于
类
类型的对象,执行该类的同步静态方法
你不应该使用等待和通知。它们是旧Java所必需的,但现在它们应该只被编写库的人使用。现在,您应该使用java.util.concurrent.Agree中的工具,即使在添加了同步之后,此代码也不会工作。如果在所有其他线程到达wait()之前,main调用notifyAll会发生什么情况?wait()会在阻止其线程之前释放对象监视器,因此不会阻止其他调用notify的线程。对于链接到此处的人,您调用的wait()
对象必须与您正在同步的对象相同。在synchronized(y)
块中调用x.wait()
将产生相同的异常。
class Runner implements Runnable
{
public void run()
{
try
{
synchronized(Main.main) {
Main.main.wait();
}
} catch (InterruptedException e) {}
System.out.println("Runner away!");
}
}