java - 通知运行在不同对象中的线程

标签 java multithreading design-patterns concurrency thread-safety

我仔细阅读了 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/

相关文章:

java - 您可以将 RSA 公共(public)指数设置为您选择的值吗?

java - 比较 int 和 long 时发生 Hibernate ClassCastException

在循环中创建线程

c++ - 全局变量外部声明后的 Threadprivate 指令

java - Controller属于Presentation层?

java - 使用Java ee进行数据库之间的通信

java - 编写关于RGB-CMY的java程序

java - 在线程中获取和设置标志变量

java - 使用 java 遍历 CIDR 中的所有 IP 地址

java - 我正在尝试理解建筑模式,但我与导演之间存在问题