我仔细阅读了 Oracle 文档,但找不到适合我的问题的设计模式解决方案。我有两个匿名线程,一个需要通知另一个。
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.a();
obj.b();
}
MyClass 有两个不同的函数,每个函数都启动一个匿名线程。 B 人希望被他的妻子 A 叫醒。
public class MyClass{
public MyClass(){
}
public void a() {
new Thread(new Runnable(){
@Override
public synchronized void run() {
System.out.println("A: I am going to sleep");
try {
Thread.sleep(1000);
System.out.println("A: I slept one full day. Feels great.");
System.out.println("A: Hey B, wake up!");
notifyAll();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
public void b() {
new Thread(new Runnable(){
@Override
public synchronized void run() {
System.out.println("B: I am going to sleep. A, please wake me up.");
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("B: Thank you A for waking me up!");
}
}).start();
}
}
不幸的是,B永远沉睡了,无法被他的妻子A叫醒。
程序的输出:
A: I am going to sleep
B: I am going to sleep. A, please wake me up.
A: I slept one full day. Feels great.
A: Hey B, wake up!
据我所知,A和B运行在两个不同的匿名线程对象中,因此A只能通知其他A(床上没有其他妻子,因此通知函数在这里没有用)。
此问题的正确设计模式是什么?
最佳答案
两个线程需要使用相同的信号量对象来锁定。
当前代码中的锁位于两个不同的对象上 - 由 a
创建的 Runnable
自身具有锁,与 b
相同code>,因此当您调用 notifyAll
时,没有对象等待锁通知。
同步块(synchronized block)内的 Thread.sleep
也存在问题。
更改代码,以便在使用 synchronized
关键字时获得锁,如下所示:
public void a()
{
new Thread(
new Runnable()
{
@Override
public void run()
{
try
{
System.out.println("A: I am going to sleep");
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
synchronized(MyClass.this)
{
System.out.println("A: I slept one full day. Feels great.");
System.out.println("A: Hey B, wake up!");
MyClass.this.notifyAll();
}
}
}
).start();
}
public void b()
{
new Thread(
new Runnable()
{
@Override
public void run()
{
synchronized(MyClass.this)
{
System.out.println("B: I am going to sleep. A, please wake me up.");
try
{
MyClass.this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("B: Thank you A for waking me up!");
}
}
}
).start();
}
关于java - 通知运行在不同对象中的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17856844/