试用一下BlockingQueue:
简单的生产者与消费者问题: 一个消费者,两个生产者
package com.concurrency.dataStucture; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class BlockingQueueTest<E> { /** * 阻塞队列的应用举例 * 生产者-消费者问题可以使用该数据类型来进行解决 */ public BlockingQueue<E> datas = null; //the cache area public BlockingQueueTest(BlockingQueue<E> datas){ this.datas = datas; } public static int consumeCounter = 0; public static int productCounter = 0; //the counter public synchronized int getConsumerCounter(){ return consumeCounter; } // public synchronized int getProductCounter(){ // return productCounter; // } // public synchronized void writeProductCounter(){ // productCounter++; // } public void run(){ //function Consumer<E> c = new Consumer<E>(datas); Productor<E> p1 = new Productor<E>(datas); Productor<E> p2 = new Productor<E>(datas); Thread t1 = new Thread(c, "ct"); Thread t2 = new Thread(p1, "pt:1"); Thread t3 = new Thread(p2, "pt:2"); t1.start(); t2.start(); t3.start(); } class Consumer<E> implements Runnable{ //consumer private final BlockingQueue<E> cache; // public static int counter=0; public Consumer(BlockingQueue<E> cache){ this.cache = cache; //cache area } @Override public void run() { //every consumer consume 20 elements; // TODO Auto-generated method stub for(int i =0;i<10;i++){ try{ consume(); //consume }catch(InterruptedException e){ System.out.println(Thread.currentThread().getName()+":"+e.getMessage()); } } } public synchronized void consume() throws InterruptedException{ E elem =cache.take(); // take the product to consume consumeCounter++; System.out.println("consume : the Num is"+getConsumerCounter()+"---------"+(String)elem); } } class Productor<E> implements Runnable{ //productor private final BlockingQueue<E> cache; public Productor(BlockingQueue<E> cache){ this.cache = cache; //cache area } @SuppressWarnings("unchecked") @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<5;i++){ // every productor product 20 elements try{ product(i); }catch(Exception e){ System.out.println(Thread.currentThread().getName()+":"+e.getMessage()); } } } public void product(int i) throws InterruptedException{ E elme = (E) new String(Thread.currentThread().getName()+"+p:"+i); // writeProductCounter(); cache.put(elme); System.out.println("product : "+"---------"+(String)elme); } } public static void main(String[] args){ BlockingQueue<String> cache = new ArrayBlockingQueue<String>(20); //capacity = 20 BlockingQueueTest<String> bqt = new BlockingQueueTest<String>(cache); bqt.run(); } }
这里给个有特点的结果:product : ---------pt:2+p:0 consume : the Num is1---------pt:1+p:0 product : ---------pt:1+p:0 consume : the Num is2---------pt:2+p:0 product : ---------pt:2+p:1 consume : the Num is3---------pt:2+p:1 product : ---------pt:1+p:1 consume : the Num is4---------pt:1+p:1 product : ---------pt:2+p:2 consume : the Num is5---------pt:2+p:2 product : ---------pt:1+p:2 consume : the Num is6---------pt:1+p:2 product : ---------pt:2+p:3 consume : the Num is7---------pt:2+p:3 product : ---------pt:1+p:3 consume : the Num is8---------pt:1+p:3 product : ---------pt:2+p:4 consume : the Num is9---------pt:2+p:4 product : ---------pt:1+p:4 consume : the Num is10---------pt:1+p:4
看结果里面的问题:打印的第一个产品是product 2-0, 但是消费的是 1-0, (Thread-i);
不要以为这里程序出问题了,这里其实没出问题,只是打印的慢了点,原因是这样的:
当product 的线程pt1执行 到cache.add(elme)的时候,cpu 切换到执行 consumer线程,然后 consumer执行完之后,又切换回pt1 接着执行 syso语句,所以这里出现这个打印顺序;
因此 ,如果在实际问题中, 需要处理的问题要 一气呵成(就是不会出现上面那种现象),可以通过synch关键字或者锁进行有效的控制。