并发编程 11—— 任务取消 之 “毒丸”对象

 

概述

第1部分 定义

第2部分 实例

 

第1部分 定义

  “毒丸”是指一个放在队列上的对象,其含义是:“当得到这个对象时,立即停止。”在FIFO 队列中,“毒丸”对象将确保消费者在关闭之前首先完成队列中的所有工作,在提交“毒丸”对象之前提交的所有工作都会被处理,而生产者在提交了“毒丸”对象后,将不会在提交任何工作。在下面的程序清单中给出了一个单生产者——单消费者的桌面搜索示例,使用了“毒丸”对象来关闭服务。

 

第2部分 实例

 1 /**
 2  * 7.17 通过“毒丸”对象来关闭服务
 3  * @ClassName: IndexingService 
 4  * @author xingle
 5  * @date 2014-11-12 下午1:58:06
 6  */
 7 public class IndexingService {
 8     private static final int CAPACITY = 1000;
 9     private static final File POISON = new File("");
10     private final IndexerThread consumer = new IndexerThread();
11     private final CrawlerThread producer = new CrawlerThread();
12     private final BlockingQueue<File> queue;
13     //private final FileFilter fileFilter;
14     private final File root;
15 
16     public IndexingService(File root) {
17         this.root = root;
18         this.queue = new LinkedBlockingQueue<File>(CAPACITY);
19         
20     }
21 
22     private boolean alreadyIndexed(File f) {
23         return false;
24     }
25 
26     //生产者
27     class CrawlerThread extends Thread {
28         public void run() {
29             try {
30                 crawl(root);
31             } catch (InterruptedException e) { /* fall through */
32             } finally {
33                 while (true) {
34                     try {
35                         System.out.println("放入“毒丸”");
36                         queue.put(POISON);
37                         break;
38                     } catch (InterruptedException e1) { /* retry */
39                     }
40                 }
41             }
42         }
43 
44         private void crawl(File root) throws InterruptedException {
45             File[] entries = root.listFiles();
46             if (entries != null) {
47                 for (File entry : entries) {
48                     if (entry.isDirectory())
49                         crawl(entry);
50                     else if (!alreadyIndexed(entry)){
51                         System.out.println("放入生产者队列文件:"+entry.getName()+" 来自线程:"+Thread.currentThread().getName());
52                         queue.put(entry);
53                     }
54                 }
55             }
56         }
57     }
58 
59     //消费者
60     class IndexerThread extends Thread {
61         public void run() {
62             try {
63                 while (true) {
64                     File file = queue.take();
65                     if (file == POISON){
66                         System.out.println("遇到“毒丸”,终止");
67                         break;
68                     }
69                         
70                     else
71                         indexFile(file);
72                 }
73             } catch (InterruptedException consumed) {
74             }
75         }
76 
77         public void indexFile(File file) {
78             System.out.println("消费者取出文件:"+file.getName()+" 来自线程:"+Thread.currentThread().getName());
79             /* ... */
80         };
81     }
82 
83     public void start() {
84         producer.start();
85         consumer.start();
86     }
87 
88     public void stop() {
89         producer.interrupt();
90     }
91 
92     public void awaitTermination() throws InterruptedException {
93         consumer.join();
94     }
95 
96 }

 

测试代码:

 1 /**
 2  * 7.17 测试主程序( 通过“毒丸”对象来关闭服务)
 3  * @ClassName: IndexingService_Main
 4  * @author xingle
 5  * @date 2014-11-12 下午2:25:36
 6  */
 7 public class IndexingService_Main {
 8     public static void main(String[] args) {
 9         File file = new File("D:\\test1/");
10         IndexingService c = new IndexingService(file);
11         c.start();
12         try {
13             TimeUnit.MICROSECONDS.sleep(100);// 停止XX时间,显示出消费速度慢于生产速度 
14         } catch (InterruptedException e) {
15             e.printStackTrace();
16         }
17         c.stop();
18     }
19 }

 

单次执行结果:

 

只有在生产者和消费者的数量都已知的情况下,才可以使用”毒丸“对象。

在 IndexingService中采用的解决方案可以扩展到多个生产者:只需每个生产者都想队列放入一个”毒丸“对象,并且消费者仅当在接收到N个生产者的”毒丸“对象时才停止。这种方法也可以扩展到多个消费者的情况,只需生产者将N个”毒丸“对象放入队列。然而,当生产者和消费者的数量较大时,这种方法将变的难以使用。只有在无界队列中,”毒丸“对象才能可靠地工作。

 

转载于:https://www.cnblogs.com/xingele0917/p/4092553.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值