有三个简单的线程。两个在运行中启动,第三个依次唤醒。
Main main = new Main(); // экземпляр, по которому вызываем методы и синхронизируемся
Thread thread1 = new Thread(() -> main.methodA());
Thread thread2 = new Thread(() -> main.methodA());
Thread thread3Notify = new Thread(() -> main.methodB());
这是一种方法,其唯一目的是让您入睡。
public synchronized void methodA() {
System.out.println("I enter methodA" + Thread.currentThread());
this.wait();
System.out.println("I am awake " + Thread.currentThread());
}
我想依次唤醒两个线程的方法。
public synchronized void methodB() {
this.notifyAll();
sleep(1000);
this.notifyAll();
}
但问题是:我在控制台中看到了这个
I enter methodAThread[Thread-0,5,main]
I enter methodAThread[Thread-1,5,main]
I am awake Thread[Thread-0,5,main]
那些。methodB 只唤醒第一个线程,第二个线程永远挂在 methodA 中。我调用 this.notifyAll() 多少次都没关系
我试图自己弄清楚,但我做不到。
我将尝试逐步解释。三个线程被启动,正如我们所知,它们的启动顺序是任意的,不受任何限制。在这种情况下,它是 - 1,3,2。第一个线程进入同步方法,阻塞监视器(如果它们已经启动,则其余的正在等待),打印一条消息并到达等待(),它释放了这个监视器。第三个线程第二次进入它的方法,锁定监视器(即第二个线程到达时将等待它的方法解锁),抛出 notifyAll() + pause + notifyAll()。现在重要的是,直到第三个线程释放监视器(基本上完成执行其方法),没有其他线程被激活。然后第三个线程完成该方法并释放监视器。监视器上有 2 个阻塞线程 - 第一个在 wait() 方法上(两个通知在这个 wait() 上到达),第二个在方法入口处。执行优先级赋予第二个线程 - 它打印第二条消息,到达 wait() 并释放监视器。执行被转移到第一个线程,它打印一条消息并结束。第二个线程继续挂在它的 wait() 上并等待一个永远不会到来的通知。
您可以通过在线程启动时使用暂停来试验线程的启动顺序,并获得不同的结果。