package ch21concurrent.examples; import java.io.File; import java.io.FileFilter; import java.util.concurrent.*; /** * IndexingService * <p/> * Shutdown with poison pill * * @author Brian Goetz and Tim Peierls */ public class IndexingService { private static final int CAPACITY = 1000; private static final File POISON = new File(""); private final IndexerThread consumer = new IndexerThread(); private final CrawlerThread producer = new CrawlerThread(); private final BlockingQueue<File> queue; private final FileFilter fileFilter; private final File root; public IndexingService(File root, final FileFilter fileFilter) { this.root = root; this.queue = new LinkedBlockingQueue<File>(CAPACITY); this.fileFilter = new FileFilter() { public boolean accept(File f) { return f.isDirectory() || fileFilter.accept(f); } }; } private boolean alreadyIndexed(File f) { return false; } class CrawlerThread extends Thread { public void run() { try { crawl(root); } catch (InterruptedException e) { /* fall through */ } finally { while (true) { try { queue.put(POISON); break; } catch (InterruptedException e1) { /* retry */ } } } } private void crawl(File root) throws InterruptedException { File[] entries = root.listFiles(fileFilter); if (entries != null) { for (File entry : entries) { if (entry.isDirectory()) crawl(entry); else if (!alreadyIndexed(entry)) queue.put(entry); } } } } class IndexerThread extends Thread { public void run() { try { while (true) { File file = queue.take(); if (file == POISON) break; else indexFile(file); } } catch (InterruptedException consumed) { } } public void indexFile(File file) { /*...*/ } ; } public void start() { producer.start(); consumer.start(); } public void stop() { producer.interrupt(); } public void awaitTermination() throws InterruptedException { consumer.join(); } }