一、线程通讯三个方法(对象级别、都是Object类 的内置方法):
一、线程通讯三个方法(对象级别、都是Object类 的内置方法):
1.wait()/wait(long timeout):线程进入休眠
2.notify:随机唤醒进入休眠状态的线程
3.notifyAll:唤醒所有处于休眠状态的线程
注意事项:以上三种方法都必须配合synchronized一起使用,否则会报错
二、wait方法的使用
首先我们来了解一下wait的执行流程:
- 使当前执行代码的线程进行等待(把线程放在等待队列中)
- 释放当前的锁
- 满足一定条件时被唤醒,重新尝试这个锁
演示代码:
package thread.threaddemo;
/**
* @Author: wenjingyuan
* @Date: 2023/01/14/23:35
* @Description:wait()方法
*/
public class WaitDemo {
public static void main(String[] args) {
Object lock=new Object();
Thread t1=new Thread(()->{
//
System.out.println("线程1开始执行");
try {
synchronized (lock){
System.out.println("线程1调用wait方法");
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1结束执行");
},"线程1");
t1.start();
}
}
三、notify使用
代码演示:
package thread.threaddemo;
/**
* @Author: wenjingyuan
* @Date: 2023/01/14/23:35
* @Description:notify()方法
*/
public class WaitDemo2 {
public static void main(String[] args) {
Object lock=new Object();
Object lock2=new Object();
Thread t1=new Thread(()->{
//
System.out.println("线程1开始执行");
try {
synchronized (lock){
System.out.println("线程1调用wait方法");
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1结束执行");
},"线程1");
t1.start();
Thread t2=new Thread(()->{
//
System.out.println("线程2开始执行");
try {
synchronized (lock){
System.out.println("线程2调用wait方法");
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程2结束执行");
},"线程2");
t2.start();
Thread t3=new Thread(()->{
//
System.out.println("线程3开始执行");
try {
synchronized (lock2){
System.out.println("线程3调用wait方法");
lock2.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程3结束执行");
},"线程3");
t3.start();
//线程4执行唤醒线程
Thread t4=new Thread(()->{
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程4开始执行");
synchronized (lock){
lock.notify();
System.out.println("线程4执行唤醒操作");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程4 执行结束");
}
},"线程4");
t4.start();
}
}
运行结果:
注意事项:notify调用之后并不是立马唤醒线程开始执行,而是要等待notify中synchronized执行结束(锁释放)才能真正的被唤醒起来开始执行
四、 notifyAll使用
代码演示:
package thread.threaddemo;
/**
* @Author: wenjingyuan
* @Date: 2023/01/14/23:35
* @Description:notify()方法
*/
public class WaitDemo3 {
public static void main(String[] args) {
Object lock=new Object();
Object lock2=new Object();
Thread t1=new Thread(()->{
//
System.out.println("线程1开始执行");
try {
synchronized (lock){
System.out.println("线程1调用wait方法");
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程1结束执行");
},"线程1");
t1.start();
Thread t2=new Thread(()->{
//
System.out.println("线程2开始执行");
try {
synchronized (lock){
System.out.println("线程2调用wait方法");
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程2结束执行");
},"线程2");
t2.start();
Thread t3=new Thread(()->{
//
System.out.println("线程3开始执行");
try {
synchronized (lock){
System.out.println("线程3调用wait方法");
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程3结束执行");
},"线程3");
t3.start();
//线程4执行唤醒线程
Thread t4=new Thread(()->{
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程4开始执行");
synchronized (lock){
lock.notifyAll();
System.out.println("线程4执行唤醒操作");
// try {
// Thread.sleep(2000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// System.out.println("线程4 执行结束");
}
},"线程4");
t4.start();
}
}
运行结果:
五、线程通讯注意事项
1.wait/notify/notifyAll必须要配合synchronized一起使用
2. wait/notify/notifyAll进行synchronized加锁的时候,一定要使用同一个对象进行加锁
3.当调用了Notify/notifyAll之后,程序不会立即恢复执行,而是尝试获取锁,只有得到锁之后才能继续执行
4.notifyAll并不是唤醒所有的wait等待的线程的,而是唤醒当前对象处于wait等待的所有线程。