ASP源码.NET源码PHP源码JSP源码JAVA源码DELPHI源码PB源码VC源码VB源码Android源码
当前位置:首页 >> 低调看直播体育app软件下载 >> Javajrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播 >> 多线程生产者、消费者模式中,如何停止消费者?多生产者情况下对“毒丸”策略的应用。

多线程生产者、消费者模式中,如何停止消费者?多生产者情况下对“毒丸”策略的应用。(1/2)

来源:网络整理     时间:2016-01-25     关键词:

本篇文章主要介绍了"多线程生产者、消费者模式中,如何停止消费者?多生产者情况下对“毒丸”策略的应用。",主要涉及到方面的内容,对于Javajrs看球网直播吧_低调看直播体育app软件下载_低调看体育直播感兴趣的同学可以参考一下: 生产者、消费者模式是多线程中的经典问题。通过中间的缓冲队列,使得生产者和消费者的速度可以相互调节。对于比较常见的单生产者、多消费者的情况,主要有以下两种策略:通...

生产者、消费者模式是多线程中的经典问题。通过中间的缓冲队列,使得生产者和消费者的速度可以相互调节。

对于比较常见的单生产者、多消费者的情况,主要有以下两种策略:

  1. 通过volatile boolean producerDone =false 来标示是否完成。生产者结束后标示为true, 消费者轮询这个变量来决定自己是否退出。 这种方式对producerDone产生比较大的争用,实现起来也有诸多问题需要考虑。

  2. 比较经典的“毒丸”策略,生产者结束后,把一个特别的对象:“毒丸”对象放入队列。消费者从队列中拿到对象后,判断是否是毒丸对象。如果是普通非毒丸对象,则正常消费。如果是毒丸对象,则放回队列(杀死其他消费者),然后结束自己。这种方式不会对结束状态产生争用,是比较好的方式。

由于“毒丸”策略是在单生产者多消费者情况下的。对于多生产者的情况,需要对之进行一些修改。我的想法是这样的。用Countdownlatch作为生产者计数器。所有生产者结束后,由协调者放入毒丸对象,消费者退出过程是一样的。上代码:

Coordinator: 启动生产者消费者,提供队列、计数器。生产者全部结束后,放入毒丸。

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;

public class Coordinator {
	public static final Object POISON_PILL = new Object();//special object to kill consumers
	private int productCount = 3;
	private int consumerCount = 5;

	public void startAll() throws Exception{
		BlockingQueue queue = new ArrayBlockingQueue(20);
		CountDownLatch noMoreToProduce = new CountDownLatch(productCount);
		//start consumers;
		for(int i = 0; i < consumerCount; i++){
			new Thread(new Consumer("consumer " + i, queue)).start();
		}
		//start producers;
		for(int i = 0; i < productCount; i++){
			new Thread(new Producer("producer " + i, queue, noMoreToProduce)).start();
		}
		//wait until all producer down
		noMoreToProduce.await();
		System.out.println("All producer finished, putting POISON_PILL to the queue to stop consumers!");
		//put poison pill
		queue.put(POISON_PILL);
	}

	public static void main(String[] args) throws Exception{
		new Coordinator().startAll();
	}
}

Producer: 随机生产和结束,结束前使countdownlatch + 1

import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;

public class Producer implements Runnable {
	private String name;
	private CountDownLatch noMoreToProduce;
	private BlockingQueue queue;
	private Random random = new Random();

	public Producer(String name, BlockingQueue queue, CountDownLatch noMoreToProduce){
		this.name = name;
		this.queue = queue;
		this.noMoreToProduce = noMoreToProduce;
	}

	@Override
	public void run() {
		System.out.println(name + " started.");
		try {
			while (true) {
				Object item = randomProduce();
				if (item == null) {
					break; //break if no more item
				}
				queue.put(item);
				System.out.println(name + " produced one.");
			}
		} catch (InterruptedException e) {
			//log
		} finally{
			System.out.println(name + " finished.");
			noMoreToProduce.countDown();//count down to signal "I finished."
		}
	}

	private Object randomProduce() {
		if (random.nextBoolean()) {
			return new Object();
		}
		return null;
	}
}

Consumer: 判断毒丸对象。如果是毒丸,放回队列(杀死其他消费者),然后自己退出。

相关图片

相关文章