Java 线程间通信
原文:https://www.studytonight.com/java/interthread-communication.php
Java 提供了避免使用线程间通信的线程池的好处。对象类的wait()
、notify()
和notifyAll()
方法用于此目的。这些方法在对象中作为最终方法实现,因此所有类都有它们。所有这三个方法只能从一个同步的上下文中调用
wait()
告诉调用线程放弃监视器并进入睡眠,直到其他线程进入同一个监视器并调用 notify。notify()
唤醒同一对象上调用 wait()的线程。notifyAll()
唤醒同一对象上所有调用 wait()的线程。
wait()
和sleep()
的区别
| 等待() | 睡眠() | | 从同步块调用 | 没有这样的要求 | | 监视器被释放 | 监视器未释放 | | 调用 notify()或 notifyAll()方法时唤醒。 | 调用 notify()或 notifyAll()方法时不会唤醒 | | 不是静态方法 | 静态法 | | wait()通常用于条件 | sleep()方法只是用来让你的线程进入睡眠状态。 |
线程池
池化通常通过循环实现,即重复检查某些条件。一旦条件成立,就采取适当的措施。这浪费了 CPU 时间。
Java 中的线程死锁
死锁是一种完全锁定的情况,此时没有线程可以因为缺乏资源而完成其执行。上图中,线程 1 持有资源 R1,需要另一个资源 R2 来完成执行,但是 R2 被线程 2 锁定,线程 2 需要 R3,R3 又被线程 3 锁定。因此,他们中没有一个人能完成任务,陷入僵局。
例子
在本例中,多个线程正在访问导致死锁情况的同一方法。当一个线程持有该资源并且不释放它时,其他线程将会等待,并且在死锁条件下,等待时间永远不会结束。
class Pen{}
class Paper{}
public class Write {
public static void main(String[] args)
{
final Pen pn =new Pen();
final Paper pr =new Paper();
Thread t1 = new Thread() {
public void run()
{
synchronized(pn)
{
System.out.println("Thread1 is holding Pen");
try{
Thread.sleep(1000);
}
catch(InterruptedException e){
// do something
}
synchronized(pr)
{
System.out.println("Requesting for Paper");
}
}
}
};
Thread t2 = new Thread() {
public void run()
{
synchronized(pr)
{
System.out.println("Thread2 is holding Paper");
try {
Thread.sleep(1000);
}
catch(InterruptedException e){
// do something
}
synchronized(pn)
{
System.out.println("requesting for Pen");
}
}
}
};
t1.start();
t2.start();
}
}
线 1 拿着笔线 2 拿着纸