chapter7 取消与关闭2

来源:互联网 发布:网络直播p2p技术简介 编辑:程序博客网 时间:2024/06/05 16:33
 1、“毒丸”对象

   一种关闭生产者-消费者服务的方式就是使用毒丸对象。毒丸是指一个放在队列上的对象,其含义是:“当得到这个对象时,立即停止”。在FIFO队列中,毒丸对象将保证在关闭之前完成队列中的所有工作。
   毒丸模式,也可以扩展为接收到N个毒丸之后才停止。
   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();    }}
2、只执行一次的服务
    对于此类场景,可以用一个私有的executor来简化服务的生命周期管理。
     public class CheckForMail {
    public boolean checkMail(Set<String> hosts, long timeout, TimeUnit unit)            throws InterruptedException {        ExecutorService exec = Executors.newCachedThreadPool();        final AtomicBoolean hasNewMail = new AtomicBoolean(false);        try {            for (final String host : hosts)                exec.execute(new Runnable() {                    public void run() {                        if (checkMail(host))                            hasNewMail.set(true);                    }                });        } finally {            exec.shutdown();            exec.awaitTermination(timeout, unit);        }        return hasNewMail.get();    }    private boolean checkMail(String host) {        // Check for mail        return false;    }}
3、未捕获异常的处理
   使用UncaughtExceptionHandler处理线程意外中止。这个比较简单,从网上找到一段实例代码:
 
import java.lang.Thread.UncaughtExceptionHandler; public class ThreadTest {   public static void main(String[] args) {    ErrHandler handle = null;    ThreadA a = null;     a = new ThreadA();    handle = new ErrHandler();    a.setUncaughtExceptionHandler(handle);// 加入定义的ErrHandler    a.start();   } } /** * 自定义的一个UncaughtExceptionHandler */class ErrHandler implements UncaughtExceptionHandler {  /**   * 这里可以做任何针对异常的处理,比如记录日志等等   */  public void uncaughtException(Thread a, Throwable e) {    System.out.println("This is:" + a.getName() + ",Message:"        + e.getMessage());    e.printStackTrace();  }} /** * 拥有UncaughtExceptionHandler的线程 */class ThreadA extends Thread {   public ThreadA() {   }   public void run() {     double i = 12 / 0;// 抛出异常的地方  } 
      
原创粉丝点击