Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java等待并通知:IllegalMonitorStateException_Java_Multithreading_Concurrency - Fatal编程技术网

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!");
  }
}