ske*_*gse 37 java concurrency multithreading
我不完全了解wait
和notify
(的Object
工作),并因此我不得不瘦下来我尝试到下面的代码部分.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
Runner.java:
class Runner implements Runnable
{
public void run()
{
try
{
Main.main.wait();
} catch (InterruptedException e) {}
System.out.println("Runner away!");
}
}
Run Code Online (Sandbox Code Playgroud)
目前我在调用时遇到IllegalMonitorStateException Main.main.wait();
,但我不明白为什么.从我所看到的,我需要同步Runner.run
,但这样做我认为它只会通知一个线程,当想法是通知他们所有.
我看过了java.util.concurrent
,但我找不到合适的替代品(也许我只是遗漏了一些东西).
dle*_*lev 62
wait()
除非当前线程拥有该对象的监视器,否则不能在对象上.要做到这一点,你必须synchronize
坚持:
class Runner implements Runnable
{
public void run()
{
try
{
synchronized(Main.main) {
Main.main.wait();
}
} catch (InterruptedException e) {}
System.out.println("Runner away!");
}
}
Run Code Online (Sandbox Code Playgroud)
同样的规则也适用于notify()
/ notifyAll()
.
该Javadoc文档wait()
提到这一点:
此方法只应由作为此对象监视器所有者的线程调用.有关
抛出:notify
线程可以成为监视器所有者的方式的说明,请参阅方法.
IllegalMonitorStateException
- 如果当前线程不是此对象监视器的所有者.
来自notify()
:
线程以三种方式之一成为对象监视器的所有者:
- 通过执行该对象的同步实例方法.
- 通过执行
synchronized
在对象上同步的语句的主体.- 对于类型的对象
Class
,通过执行该类的同步静态方法.
你打电话都wait
和notifyAll
不使用synchronized
块.在这两种情况下,调用线程必须拥有您调用方法的监视器上的锁.
从文档notify
(wait
并notifyAll
有类似的文档,但参考notify
最完整的描述):
此方法只应由作为此对象监视器所有者的线程调用.线程以三种方式之一成为对象监视器的所有者:
- 通过执行该对象的同步实例方法.
- 通过执行在对象上同步的synchronized语句的主体.
- 对于Class类型的对象,通过执行该类的同步静态方法.
一次只有一个线程可以拥有对象的监视器.
只有一个线程能够一次实际退出 wait
,notifyAll
因为他们都必须再次获得相同的监视器 - 但是所有线程都会被通知,所以只要第一个线程退出同步块,下一个将获得锁等