一 体系化深入学习并发编程由简入繁系统梳理并发知识点( 六 )


这个方法必须在修饰的代码内部使用,因为该方法只能由获取了锁的线程来调用 。
下面是官方文档关于这个方法的部分描述
theto wait untilthe ()or the ()for this .
Themust own this ’s . Theof thisand waits untilon this ’sto wake upa call to theor the. Thethen waits until it can re-of theand.
Thisonly beby athat is the owner of this ’s .
方法:唤醒某一个正在等待对象的锁的线程,但是是随机唤醒的 。
唤醒之后,被唤醒的线程并不能立刻运行,因为锁还被当前线程持有(执行方法的线程),知道该线程释放锁后,被唤醒的线程才能去竞争
下面也是截选了部分官方文档
Wakes up athat ison this ’s . If anyareon this , one of them isto be . Theisandat theof the .
Thewill not be able tountil thethe lock on this . Thewillin the usualwith any otherthat might betoon this ;
Thisonly beby athat is the owner of this ’s .
Only oneat a time can own an ’s .
方法:顾名思义,它是直接唤醒所有等待该对象的的线程,执行完释放锁后,让所有等待该锁的线程都去竞争
除了这句,其他的描述都和大致相同
Wakes up allthat areon this ’s .
由此我们可以知道,以下几种情况,可以使一个已进入等待的线程被唤醒
另一个持有锁的线程使用正好唤醒了本线程另一个持有锁的线程使用唤醒了所有线程调用wait时传入了参数(等待时间,0为永久等待),超时则被唤醒线程调用了
下面演示一下几个方法的使用
public class WaitNotify {//设置一个普通对象public static Object object = new Object();public static void main(String[] args) throws InterruptedException {//线程1获取到锁后进入等待,释放锁Thread thread1 = new Thread(()->{synchronized (object){try {System.out.println(Thread.currentThread().getName()+"获取到monitor");object.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"结束");}});//线程2获取到锁后,唤醒线程1,自己运行完后,线程1再运行Thread thread2 = new Thread(()->{synchronized (object){System.out.println(Thread.currentThread().getName()+"获取到monitor");object.notify();System.out.println(Thread.currentThread().getName()+"结束");}});thread1.start();Thread.sleep(100);thread2.start();}}
按照逻辑,线程1先获取到锁,进入等待状态,释放锁
线程2此时得到锁,唤醒线程1,执行完自己的逻辑后,释放锁
线程1再度获得锁,执行剩下的命令 。
打印结果:
Thread-0获取到monitorThread-1获取到monitorThread-1结束Thread-0结束
再来试试的使用:
public class WaitNotifyAll {public static Object object = new Object();public static void main(String[] args) throws InterruptedException {WaitThread waitThread = new WaitThread(object);//设置三个线程来争夺锁new Thread(waitThread).start();new Thread(waitThread).start();new Thread(waitThread).start();//让三个线程都进入等待状态Thread.sleep(1000);//让唤醒线程来唤醒所有等待的线程new Thread(()->{synchronized (object){System.out.println("唤醒线程获取到monitor");object.notifyAll();System.out.println("唤醒线程执行结束");}}).start();}}class WaitThread implements Runnable{private Object object;public WaitThread(Object object) {this.object = object;}@Overridepublic void run() {synchronized (object){try {System.out.println(Thread.currentThread().getName()+"获取到monitor");object.wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"结束");}}}
打印结果如下:
Thread-0获取到monitorThread-2获取到monitorThread-1获取到monitor唤醒线程获取到monitor唤醒线程执行结束Thread-1结束Thread-2结束Thread-0结束