基于BlockingQueue实现与之前的基于synchronized方法实现的不同,这里不需要单独创建仓库类,用队列替代仓库,简化编程。
BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞。被阻塞的情况主要有如下两种:
负责生产的线程不断的制造新对象并插入到阻塞队列中,直到达到这个队列的上限值。队列达到上限值之后生产线程将会被阻塞,直到消费的线程对这个队列进行消费。同理,负责消费的线程不断的从队列中消费对象,直到这个队列为空,当队列为空时,消费线程将会被阻塞,除非队列中有新的对象被插入。
实现代码如下:
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(); } } } }