线程间通信
- 什么是线程通信
多个线程在处理同一个资源,并且任务不同时,需要线程通信来帮助解决线程之间对同一个变量的使用或操作。
就是多个线程在操作同一份数据时, 避免对同一共享变量的争夺。
于是我们引出了等待唤醒机制:wait()、notify()
就是在一个线程进行了规定操作后,就进入等待状态wait,等待其他线程执行完他们的指定代码过后,再将其唤醒notify。 - wait/notify/notifyAll机制的使用与分析
1.Synchrnoized加锁的线程的Object类的wait/notify/notifyAll
2.被finish修饰(密封)的方法不能被继承,被finish修饰(密封)的类不能被继承
注意:看到monitor就要想到Synchrnoized
1)wait/notify/notifyAll这三个方法是本地方法,同时是final方法,无法被重写
2)
wait()使得当前线程进入阻塞(后面的代码块不会执行)
notify()唤醒一个正在等待当前对象monitor锁的线程,如果有多个线程都在等待对象的monitor,随机选择一个唤醒
notifyAll()唤醒所有正在等待当前对象的monitor锁的线程
问题:跟线程相关的方法一般都会定义到Thread类,但wait/notify/notifyAll被定义到Object类中,为什么?
答:有很多个线程等待当前对象的锁,这多个线程有可能不止是等待当前这一个对象的锁,很多线程等待很多的锁,那通过线程对象去操作就比较复杂 - wait和sleep的区别
1)
sleep:Thread类方法,用来线程的执行流程
wait:Object类的方法,用于线程间的通信
2)关于锁的释放,sleep不会释放资源,wait会释放资源
3)wait在同步代码块中,sleep不会在同步代码块中
4)wait和sleep都会抛出异常 - await/signal/signalAll机制和的使用与分析
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
等待唤醒机制
生产者和消费者案例
生产者生产的产品给店员,消费者从店员那获取产品
使用lock同步锁
lock同步锁也有自己的线程等待和唤醒机制
通过Lock同步锁实现线程的通信,必须依赖Condition实例
Condition
await()
signal()
signalALL()
Condition实例实质上被绑定到一个锁上
为特定的Lock实例获得Condition实例,使用newCondition()方法
- 生产者消费者模型
生产线程 | 队列 | 消费线程
put() | take() | 可阻塞
1.put(),如果队列已经满,put将会阻塞直到队列中有空间可用
2.take(),如果队列已经空,take将会阻塞直到队列数据可用