之前介绍了两种简单的结束线程任务的方法,对于线程相互协作工作的应用场景,例如生成消费者模式中,生产者决定要停止生产了,生产者应该告诉消费者“我已经停止生产了,你不要等啦”。如上一篇,生产者可以中断消费者线程,但生产者并不知道消费者此时的消费速度,生产者必须等到消费者全部消费完或者直接中断(通常不是一个好主意),而且生产者并不拥有消费者的所有权,所以并不是一种行之有效的方式;还有一种比较简单且容易实现的方式让生产线程通知消费线程结束自己,即利用“毒丸对象”。
例如:
生产者产生随机数,但生产者生产到数字0时,产生毒丸对象放入到生产队列中,立即停止生产,消费者接受生产者生产的数据,简单打印出来,当接收到毒丸对象时,消费者停止消费。
public class ThreadCacell4 { private final BlockingQueue<Integer> queue = new LinkedBlockingQueue<Integer>(); private Random ramdom = new Random(); class Producer implements Runnable { public void run() { while(true) { int randomInt = ramdom.nextInt(10); if (randomInt == 0) { queue.add(Integer.MAX_VALUE); System.out.println("Producer will stop now, and set Poison element:"+Integer.MAX_VALUE); break; } else {queue.add(randomInt);} } } } class Consumer implements Runnable { public void run() { while(true) { try { int element = queue.take().intValue(); int posion = Integer.MAX_VALUE; boolean flag = (element == posion); if(flag) { System.out.println(); System.out.println("No elements need deal with, Consumer will stop now."); break; } else { System.out.print("["+element+"=="+posion+"]="+(element==posion)+ " "); } } catch (InterruptedException e) { e.printStackTrace(); } } } } /** * @param args */ public static void main(String[] args) { ThreadCacell4 thread = new ThreadCacell4(); Thread producer = new Thread(thread.new Producer()); Thread consumer = new Thread(thread.new Consumer()); producer.start(); consumer.start(); System.out.println(); } }
测试结果:
Producer will stop now, and set Poison element:2147483647
[3==2147483647]=false [6==2147483647]=false [1==2147483647]=false [1==2147483647]=false [1==2147483647]=false [7==2147483647]=false
No elements need deal with, Consumer will stop now.
如果有N个消费者,那么请在生产者结束前,生产N个毒丸对象。