企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] <br/> > ### `wait/notify` * 等待/通知的相关方法是任意Java对象都具备的,因为这些方法被定义在所有对象的超类`java.lang.Object`上。 ![](https://i.loli.net/2019/03/10/5c851dd4b9ff0.png) * 使用`wait()`、`notify()`和`notifyAll()`时需要先对调用对象加锁。 * 调用`wait()`方法后,线程状态由`RUNNING`变为`WAITING`,并将当前线程放置到对象的等待队列。 * `notify()`或`notifyAll()`方法调用后,等待线程依旧不会从`wait()`返回,需要调用`notify()`或`notifAll()`的线程释放锁之后,等待线程才有机会从`wait()`返回。 * `notify()`方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而`notifyAll()`方法则是将等待队列中所有的线程全部移到同步队列,被移动的线程状态由`WAITING`变为`BLOCKED`。 * 从`wait()`方法返回的前提是获得了调用对象的锁。 <br/> > ### `sleep`和`wait`的区别 * `sleep`是`Thread`类的方法,`wait`是`Object`类中定义的方法 * `Thread.sleep`不会导致锁行为的改变,如果当前线程是拥有锁的,那么`Thread.sleep`不会让线程释放锁。和锁相关的方法都定义在`Object`类中,因此调用`Thread.sleep`是不会影响锁的相关行为。 * `wait`必须在`synchronized`块中。`wait`执行时会释放对象锁,通过使用`notify`或者`notifyAll`来唤醒 <br/> > ### 等待/通知的经典范式 * 等待方遵循如下原则 * 1)获取对象的锁。 * 2)如果条件不满足,那么调用对象的wait()方法,被通知后仍要检查条件。 * 3)条件满足则执行对应的逻辑。 ``` synchronized(对象) { while(条件不满足) { 对象.wait(); } 对应的处理逻辑 } ``` * 通知方遵循如下原则 * 1)获得对象的锁。 * 2)改变条件。 * 3)通知所有等待在对象上的线程。 ``` synchronized(对象) { 改变条件对象.notifyAll(); } ``` <br/> > ### 两个线程交替输出奇偶数到100`synchronized` `wait/notify` ``` public class Demo1 { //两线程共享的变量 static int i = 1; public static class ThreadDemo implements Runnable{ Object lock; public ThreadDemo(Object lock) { this.lock = lock; } public void run() { synchronized(lock){ while(i <= 100){ System.out.println(Thread.currentThread().getName() + ":" + i); i++; lock.notify(); try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } public static void main(String[] args) { Object lock = new Object(); Thread t1 = new Thread(new ThreadDemo(lock), "thread1"); Thread t2 = new Thread(new ThreadDemo(lock), "thread2"); t1.start(); t2.start(); } } ``` <br/> > ### 三个线程交替输出数字到100`synchronized` `wait/notify` ``` public class Demo2{ static int i = 1; static class ThreadDemo implements Runnable{ Object lock; int t; public ThreadDemo(Object lock, int t){ this.lock = lock; this.t = t; } public void run(){ synchronized(lock){ while(i <= 100){ if(i % 3 == t){ System.out.println(Thread.currentThread().getName() + ":" + i); i++; lock.notifyAll(); }else{ try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } } public static void main(String[] args) { Object lock = new Object(); for(int i = 0; i < 3; i++){ Thread t = new Thread(new ThreadDemo(lock, i), "thread" + (i + 1)); t.start(); } } } ```