生产者/消费者模式是为了解耦消费者和生产者而产生的,其原理很是地简单。总的来讲就是生产者和消费者之间不直接通讯,而是借助一个第三方(一般是阻塞队列)
,第三方也成为临界资源,同一时间只容许一条线程对其进行操做。java
notify/wait
机制实现全部的注释都写在代码中,在这里咱们模仿在水桶中存水和取水的过程:bash
Main.java
ide
package com.wokao66.consumerProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 测试
* @author: huangjiawei
* @since: 2018年4月3日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public class Main {
public static void main(String[] args) {
/**
* 新建一个水桶,存放全部的水,刚开始水桶是空的,容量为5L
*/
List<Water> waterList = new ArrayList<>(5);
ExecutorService executors = Executors.newFixedThreadPool(10);
WaterProvider provider = new WaterProvider(waterList);
WaterConsumer consumer = new WaterConsumer(waterList);
executors.execute(provider);
executors.execute(consumer);
}
}
复制代码
WaterProvider.java
测试
package com.wokao66.consumerProvider;
import java.util.List;
/**
* 往桶里加水的生产者
* @author: huangjiawei
* @since: 2018年4月3日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public class WaterProvider implements Runnable {
/**
* 这是咱们的水桶(10L)
*/
private List<Water> waterList = null;
/**
* 初始化水桶,也就是缓冲区
*/
public WaterProvider(List<Water> waterList) {
this.waterList = waterList;
}
@Override
public void run() {
/**
* 循环任务,也就是这个任务会执行屡次,没有明确的break语句或者异常,该任务不会终止
*/
while (true) {
/**
* 这里得到waterList的锁,以前说过notify、wait的使用必须先得到锁
*/
synchronized (waterList) {
/**
* 判断是否是满了,满了就不生产了
*/
while (waterList.size() == 5) {
try {
/**
* 这里将所释放掉waterList的锁
*/
waterList.wait();
} catch (InterruptedException e) {}
}
/**
* 若是尚未满,那么就加1L水进去,加进去以前
*/
waterList.add(new Water());
System.err.println("生产了1L水,如今水桶有:" + waterList.size() + "L水");
try {
/**
* sleep方法是不会释放锁的
*/
Thread.sleep(1000);
} catch (InterruptedException e) {}
/**
* 我通知全部的消费者来消费
*/
waterList.notifyAll();
}
}
}
}
复制代码
WaterConsumer.java
ui
package com.wokao66.consumerProvider;
import java.util.List;
/**
* 往桶里取水的消费者
* @author: huangjiawei
* @since: 2018年4月3日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public class WaterConsumer implements Runnable {
private List<Water> waterList;
public WaterConsumer(List<Water> waterList) {
this.waterList = waterList;
}
@Override
public void run() {
/**
* 循环任务,也就是这个任务会执行屡次,没有明确的break语句或者异常,该任务不会终止
*/
while (true) {
/**
* 得到锁
*/
synchronized (waterList) {
/**
* 证实没有水能够消费
*/
while (waterList.isEmpty()) {
try {
/**
* 释放锁
*/
waterList.wait();
} catch (InterruptedException e) {}
}
/**
* 每次我都移动第一个元素
*/
waterList.remove(0);
System.err.println("消费了1L水,如今水桶有:" + waterList.size() + "L水");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {}
/**
* 通知生产者生产
*/
waterList.notifyAll();
}
}
}
}
复制代码
Water.java
this
package com.wokao66.consumerProvider;
/**
* 水这种类型
* @author: huangjiawei
* @since: 2018年4月3日
* @version: $Revision$ $Date$ $LastChangedBy$
*/
public class Water {
/**
* 单位L
*/
private String unit;
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
}
复制代码
执行结果:spa
生产了1L水,如今水桶有:1L水
生产了1L水,如今水桶有:2L水
消费了1L水,如今水桶有:1L水
消费了1L水,如今水桶有:0L水
生产了1L水,如今水桶有:1L水
生产了1L水,如今水桶有:2L水
消费了1L水,如今水桶有:1L水
消费了1L水,如今水桶有:0L水
生产了1L水,如今水桶有:1L水
消费了1L水,如今水桶有:0L水
生产了1L水,如今水桶有:1L水
生产了1L水,如今水桶有:2L水
生产了1L水,如今水桶有:3L水
生产了1L水,如今水桶有:4L水
生产了1L水,如今水桶有:5L水
消费了1L水,如今水桶有:4L水
消费了1L水,如今水桶有:3L水
消费了1L水,如今水桶有:2L水
消费了1L水,如今水桶有:1L水
复制代码
执行结果可能会不一致,但数据正确便可!线程