并发设计模式---生产者/消费者模式

1、什么是生产者消费者模式?

生产者/消费者模式是为了解耦消费者和生产者而产生的,其原理很是地简单。总的来讲就是生产者和消费者之间不直接通讯,而是借助一个第三方(一般是阻塞队列),第三方也成为临界资源,同一时间只容许一条线程对其进行操做。java

  • 一、当临界资源满了,生产者必须阻塞等待;
  • 二、当临界资源为空,消费者必须阻塞等待,通知生产者生产;

2、使用简单的notify/wait机制实现

全部的注释都写在代码中,在这里咱们模仿在水桶中存水和取水的过程:bash

Main.javaide

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.javaui

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.javathis

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水
复制代码

执行结果可能会不一致,但数据正确便可!线程

相关文章
相关标签/搜索