Java并发(五):线程之间的协作

Java并发(五):线程之间的协作

前面的笔记中提到了,当使用线程来同时运行多个任务时,可以通过使用锁(互斥)来同步两个任务,从而使得一个任务不会干涉另一个任务的资源。而当多个线程可以一起工作去解决某个问题时,如果某些部分必须在其它部分之前完成,那么就需要对线程进行协调
关于协调的一种方式join(),在笔记:Java并发(二):基本线程机制之再续前缘中有使用方式的介绍。接下来介绍的是线程之间协调的其他方式。

一、wait()、notify()和notifyAll()
调用wait()使得线程等待某个条件满足,线程在等待时被挂起,当其他线程的运行使得这个条件满足时,其它线程会调用notify()或者notifyAll()来换线挂起的线程
wait()、notify()和notifyAll()都是属于Object的一部分,而不是属于Thread。并且只能用在同步方法或者同步控制块中,否则在运行时会抛出IllegalMnitorStateException。
使用wait()挂起期间,线程会释放锁。这是因为,如果没有释放锁,那么其它线程就无法进入对象的同步方法或者同步控制块中,也就无法执行notify()或者notifyAll()来唤醒挂起的线程,造成死锁。
在这里插入图片描述
Ps:wait()方法可以指定线程的等待时间。因此时间到期之后,线程也会恢复
wait()和sleep()的区别:
 wait()是Object的方法,sleep()是Thread的静态方法。
wait()会释放锁,而sleep()不会
在这里插入图片描述
值得一提的是,join()是通过wait()来实现的,因此使用join()也能够释放锁
notify()和notifyAll()的区别:
对于多个任务的单个对象处于wait()状态,调用notifyAll()方法比调用notify()方法更安全。notify()方法在众多等待同一个锁的任务中只有一个会被唤醒,因此除非能够保证被唤醒的是恰当的任务(例如所有任务等待相同的条件),否则由于线程调度机制的非确定性,可能会导致死锁。而notifyAll()则是唤醒所有等待同一个锁的所有任务
而事实上,notifyAll()真正唤醒的是等待该条件的任务,并非所有任务
在这里插入图片描述

二、await()、signal()以及signalAll()
Java SE5的java.util.concurrent类库中提供了Condition类来实现线程之间的协作,可以在Condition上调用await()方法使线程等待,其它线程调用signal()或signalAll()方法唤醒等待的线程
相比于wait()这种等待方式,await()可以指定等待的条件,因此更加灵活。
在这里插入图片描述

参考资料:《Java编程思想》
CS-Notes/Java 并发.md

原创文章 78 获赞 25 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_38196407/article/details/90040337
今日推荐