经典的生产者与消费者模型(基于BlockingQueue队列实现)

基于BlockingQueue实现与之前的基于synchronized方法实现的不同,这里不需要单独创建仓库类,用队列替代仓库,简化编程。

BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种:

1. 当队列满了的时候进行入队列操作
2. 当队列空了的时候进行出队列操作

负责生产的线程不断的制造新对象并插入到阻塞队列中,直到达到这个队列的上限值。队列达到上限值之后生产线程将会被阻塞,直到消费的线程对这个队列进行消费。同理,负责消费的线程不断的从队列中消费对象,直到这个队列为空,当队列为空时,消费线程将会被阻塞,除非队列中有新的对象被插入。

实现代码如下:

package queue.producer.consumer;

import java.util.concurrent.*;

/**
 * 生产者与消费者
 * @author tiger
 * @Date 2017年7月27日
 */
public class ProducerAndConsumerQueue {
	public static void main(String[] args) throws InterruptedException {
		//替代仓库类
		BlockingQueue queue  = new ArrayBlockingQueue(20);
		
		Producer pro1 = new Producer(queue);
		Producer pro2 = new Producer(queue);
		Salesman con = new Salesman(queue);
		
		Thread make1 = new Thread(pro1,"1号生产机器");//生产者线程 1 号
		Thread make2 = new Thread(pro2,"2号生产机器");//生产者线程 2 号
		
		Thread cons1 = new Thread(con,"老鼠销售员1");//销售员线程1
		Thread cons2 = new Thread(con,"老虎销售员2");//销售员线程2
		Thread cons3 = new Thread(con,"蓝猫销售员3");//销售员线程3
		Thread cons4 = new Thread(con,"兔子销售员4");//销售员线程4
		Thread cons5 = new Thread(con,"小红销售员5");//销售员线程5
		
		make1.start();
		make2.start();
		cons1.start();
		cons2.start();
		cons3.start();
		cons4.start();
		cons5.start();
	}
}
package queue.producer.consumer;

import java.util.concurrent.*;
/**
 * 生产者
 * @author tiger
 * @Date 2017年7月28日
 */
class Producer implements Runnable{
	//持有队列,类似于仓库
	final BlockingQueue queue ;
	
	public Producer(BlockingQueue queue) {
		this.queue = queue;
	}
	public void productGoods(){
		//货物ID
		int ran = (int) (Math.random()*1000);
		//生产者名称
		String name = Thread.currentThread().getName();
		String id = String.valueOf(ran);
		try {
			queue.put(id);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//生产货物
		System.out.println(name+" 生产一个货物["+id+"],现在货物数量" + queue.size());
	}
	@Override
	public void run() {
		//仓库只要没有满就一直不停在生产货物
		while (true) {
			productGoods();
			//模拟每个货物生产需要花费的时间
			try {
				TimeUnit.MICROSECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
package queue.producer.consumer;

import java.util.concurrent.*;
/**
 * 销售员
 * @author tiger
 * @Date 2017年7月27日
 */
class Salesman implements Runnable{
	//代替了面包店
	final BlockingQueue queue ;
	public Salesman(BlockingQueue queue) {
		this.queue = queue;
	}

	public void sellGoods(){
		String name = Thread.currentThread().getName();
		try {
			String id = queue.take();
			System.out.println(name+" 卖掉一个货物["+id+"],现在货物数量" + queue.size());
			System.out.println("------------------------------");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		//仓库只要有货物就一直不停卖
		while (true) {
			sellGoods();
			//模拟卖一个货物所需要花费的时间
			try {
				TimeUnit.MICROSECONDS.sleep(5000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	} 
}

你可能感兴趣的:(线程)