线程间通信Object的waitnotify
wait/notify等待通知方式
等待通知机制就是将处于等待状态的线程将由其它线程发出通知后重新获取CPU资源,继续执行之前没有执行完的任务。最典型的例子生产者–消费者模式
生产者想要在队列中添加产品,消费者需要从队列中取出产品,如果队列为空,消费者应该等待生产者添加产品后才进行消费,队列为满时,生产者需要等待消费者消费一部分产品后才能继续生产。队列可以认为是java模型里的临界资源,生产者和消费者认为是不同的线程,它们需要交替的占用临界资源来进行各自方法的执行,所以就需要线程间通信。
等待/通知机制主要提供了三个方法用于线程间的通信
wait()当前线程释放锁并进入等待(阻塞)状态
notify()唤醒一个正在等待相应对象锁的线程,使其进入就绪队列,以便在当前线程释放锁后继续竞争锁
notifyAll()唤醒所有正在等待相应对象锁的线程,使其进入就绪队列,以便在当前线程释放锁后继续竞争锁
等待/通知机制是指一个线程A调用了对象Object的wait()方法进入等待状态,而另一线程B调用了对象Object的notify()或者notifyAll()方法,当线程A收到通知后就可以从对象Object的wait()方法返回,进而执行后序的操作。线程间的通信需要对象Object来完成,对象中的wait()、notify()、notifyAll()方法就如同开关信号,用来完成等待方和通知方的交互。
等待/通知的相关方法:
实例
场景—两个线程,一个线程对当前数值加1,另一个线程对当前数值减1,一共执行10次
假设这个共享变量的初始值为0,一个线程t1对值+1,另一个线程t2对值-1.
package com.dongguo.concurrent.waitnotify;
/** * @author Dongguo * @date 2021/9/3 0003-13:15 * @description: 生产者消费者 * 场景---两个线程,一个线程对当前数值加1,另一个线程对当前数值减1,一共执行10次 * 假设这个共享变量的初始值为0,一个线程对值+1,另一个线程对值-1. */
public class ThreadWaitNotifyDemo {
public static void main(String[] args) {
Number number = new Number();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
number.incry();
}
}, "t1").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
number.decry();
}
}, "t2").start();
}
}
class Number {
private int count;
public synchronized void incry() {
if (count != 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println(Thread.currentThread().getName() + "加一成功,count值为:" + count);
this.notifyAll();
}
public synchronized void decry() {
if (count == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println(Thread.currentThread().getName() + "减一成功,count值为:" + count);
this.notifyAll();
}
}
运行结果:
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
t1加一成功,count值为:1
t2减一成功,count值为:0
调用wait()、notify()以及notifyAll()时需要注意的细节,。
1)使用wait()、notify()和notifyAll()时需要先对调用对象加锁。
2)调用wait()方法后,线程状态由RUNNING变为WAITING,并将当前线程放置到对象的
等待队列。
3)notify()或notifyAll()方法调用后,等待线程依旧不会从wait()返回,需要调用notify()或
notifAll()的线程释放锁之后,等待线程才有机会从wait()返回。
4)notify()方法将等待队列中的一个等待线程从等待队列中移到同步队列中,而notifyAll()
方法则是将等待队列中所有的线程全部移到同步队列,被移动的线程状态由WAITING变为
BLOCKED。
5)从wait()方法返回的前提是获得了调用对象的锁。
从上述细节中可以看到,等待/通知机制依托于同步机制,其目的就是确保等待线程从
wait()方法返回时能够感知到通知线程对变量做出的修改。
还没有评论,来说两句吧...