如何在Java中使用wait/notify同步操作不同对象的两个线程?
如何在Java中使用wait/notify同步操作不同对象的两个线程?
兄弟,我懂你现在的困惑——想让两个线程按指定顺序输出,但对着wait/notify有点摸不着头脑对吧?咱们先理清你要的目标顺序:先线程1打den,然后线程2打den,接着线程1打ada,最后线程2打ada。核心就是用两个锁对象(den和ada)来做信号传递,让线程之间互相“打招呼”,告诉对方“我做完了,该你了”。
先说说你之前代码的问题:线程2一上来就死等ada的唤醒,但根本没人去通知它;而且线程1的逻辑也没对齐,没等线程2完成den的打印就直接走了,自然出不来你要的顺序。
给你改好的代码,咱们一步步拆解:
class MyThreads { public final static Object den = new Object(); public final static Object ada = new Object(); public static Thread t1 = new Thread() { public void run() { // 第一步:线程1先打印den System.out.println("Thread 1 den"); // 通知线程2:我den打完了,你可以打了 synchronized (den) { den.notify(); } // 线程1等一等,等线程2打完den再打ada synchronized (ada) { try { ada.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 线程1打印ada System.out.println("Thread 1 ada"); // 通知线程2:我ada打完了,该你了 synchronized (ada) { ada.notify(); } } }; public static Thread t2 = new Thread() { public void run() { // 线程2先等着,等线程1打完den再动 synchronized (den) { try { den.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 线程2打印den System.out.println("Thread 2 den"); // 通知线程1:我den打完了,你可以打ada了 synchronized (ada) { ada.notify(); } // 线程2等一等,等线程1打完ada再打自己的ada synchronized (ada) { try { ada.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } // 线程2打印ada System.out.println("Thread 2 ada"); } }; }
咱们走一遍执行流程,你就懂了:
- 两个线程启动后,线程2会先钻进
synchronized(den)块调用wait(),释放den的锁,进入等待状态; - 线程1拿到CPU时间,先打印"Thread 1 den",然后进入den的同步块,调用
notify()唤醒线程2,之后自己钻进ada的同步块调用wait(),释放ada的锁,开始等; - 被唤醒的线程2继续执行,打印"Thread 2 den",然后进入ada的同步块调用
notify()唤醒线程1,接着自己又钻进ada的同步块调用wait()等通知; - 被唤醒的线程1打印"Thread 1 ada",再调用
notify()唤醒线程2,然后线程1结束; - 最后线程2被唤醒,打印"Thread 2 ada",完成所有流程。
这里有几个必须注意的点,踩坑了就会出问题:
wait()和notify()必须在同一个对象的同步块/方法里调用,不然会直接抛异常;- 调用
wait()的时候,线程会自动释放当前持有的对象锁,不然其他线程根本拿不到锁来唤醒它; - 如果有多个线程等同一个对象,建议用
notifyAll()代替notify(),避免唤醒错线程,不过咱们这里只有两个线程,用notify()没问题。
备注:内容来源于stack exchange,提问作者pure21_h




