java原生的线程协同机制
线程协同.png
- blocked: 需要获得锁,从runnable->blocked;
获得锁blocked->runnable; - waiting: java线程为了协调各个线程工作的一种特殊方式;(ps:1.0就已经存在)
(time waiting是waiting的一种特殊机制,待超时等待)
举例:
- 线程 :一个工人
- 代码 :一份说明书
- 同步对象 :一个印章
- wait() :拿到印章,把自己的名字加入等待队列,然后把印章放回去
- notify() : 拿到印章,挑一个等待队列的人通知一下
- notifyAll() : 拿到印章,把等待队列的人全部通知一下
注意: 一定要和一个对象(monitor)协同
[面试题]wait和sleep有什么区别?
- wait放弃印章(放弃资源);sleep趴在印章上睡着了(不放弃资源);
实现消费者/生产者模型
public class Main {
public static void main(String[] args) throws InterruptedException {
// 生产一个,消费一个,交替循环
Container container = new Container();
Producer producer = new Producer(container);
Consumer consumer = new Consumer(container);
producer.start();
consumer.start();
producer.join();
consumer.join();
}
static class Container extends Thread {
Object value;
}
static class Producer extends Thread {
Container container;
public Producer(Container container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (container) {
// 若条件不满足,就等待
while (null != container.value) {
try {
container.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//条件满足就生产,并通知别人
int random = new Random().nextInt();
System.out.println("Producing " + random);
container.value = random;
container.notify();
}
}
}
}
/**
* 消费者与生产者完全相反
*/
static class Consumer extends Thread {
Container container;
public Consumer(Container container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
synchronized (container) {
// 若条件不满足,就等待
while (null == container.value) { //不能使用if()条件进行判断,因为存在中断或者虚假唤醒,所以为了在不满足条件的时候还能够继续sleep,不能用if()判断 (存在虚假唤醒的原因: java线程调度完全取决于CPU,所以在CPU与操作系统层面上存在虚假唤醒)
try {
container.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//条件满足就消费,并通知别人
System.out.println("Consuming " + container.value);
container.value = null;
container.notify();
}
}
}
}
}