zoukankan      html  css  js  c++  java
  • 6.多线程--取消与关闭

    一.任务取消

      其中一种协作机制能设置某个“已请求取消(Cancellation Requested)”标志,而任务将定期地查看该标志。如果设置了这个标志,那么任务将提前结束。

    @ThreadSafe
    public class PrimeGenerator implements Runnable {
        private static ExecutorService exec = Executors.newCachedThreadPool();
    
        @GuardedBy("this") private final List<BigInteger> primes
                = new ArrayList<BigInteger>();
        private volatile boolean cancelled;
    
        public void run() {
            BigInteger p = BigInteger.ONE;
            while (!cancelled) {
                p = p.nextProbablePrime();
                synchronized (this) {
                    primes.add(p);
                }
            }
        }
    
        public void cancel() {
            cancelled = true;
        }
    
        public synchronized List<BigInteger> get() {
            return new ArrayList<BigInteger>(primes);
        }
    
        static List<BigInteger> aSecondOfPrimes() throws InterruptedException {
            PrimeGenerator generator = new PrimeGenerator();
            exec.execute(generator);
            try {
                SECONDS.sleep(1);
            } finally {
                generator.cancel();
            }
            return generator.get();
        }
    }

    1.中断

      在下面的BrokenPrimeProducer就说明了这个问题。生产者线程生成素数,并将它们放入一个阻塞队列。如果生产者的速度超过了消费者的处理速度,队列将被填满,put方法也会阻塞。当生产者在put方法中阻塞时,如果消费者希望取消生产者任务,那么将发生什么情况﹖它可以调用cancel方法来设置cancelled标志,但此时生产者却永远不能检查这个标志,因为它无法从阻塞的put方法中恢复过来(因为消费者此时已经停止从队列中取出素数,所以put方法将一直保持阻塞状态)。

    class BrokenPrimeProducer extends Thread {
        private final BlockingQueue<BigInteger> queue;
        private volatile boolean cancelled = false;
    
        BrokenPrimeProducer(BlockingQueue<BigInteger> queue) {
            this.queue = queue;
        }
    
        public void run() {
            try {
                BigInteger p = BigInteger.ONE;
                while (!cancelled)
                    queue.put(p = p.nextProbablePrime());
            } catch (InterruptedException consumed) {
            }
        }
    
        public void cancel() {
            cancelled = true;
        }
    }

      每个线程都有一个boolean类型的中断状态。当中断线程时,这个线程的中断状态将被设置为true。在Thread中包含了中断线程以及查询线程中断状态的方法,如下面程序所示。interrupt方法能中断目标线程,而isInterrupted方法能返回目标线程的中断状态。静态的interrupted方法将清除当前线程的中断状态,并返回它之前的值,这也是清除中断状态的唯一方法。 

      BrokenPrimeProducer中的问题很容易解决(和简化)﹔使用中断而不是boolean标志来请求取消,如下面程序所示。在每次迭代循环中,有两个位置可以检测出中断;在阻塞的put方法调用中,以及在循环开始处查询中断状态时。由于调用了阻塞的put方法,因此这里并不一定需要进行显式的检测,但执行检测却会使PrimeProducer对中断具有更高的响应性,因为它是在启动寻找素数任务之前检查中断的,而不是在任务完成之后。如果可中断的阻塞方法的调用频率并不高,不足以获得足够的响应性,那么显式地检测中断状态能起到一定的帮助作用。 

    public class PrimeProducer extends Thread {
        private final BlockingQueue<BigInteger> queue;
    
        PrimeProducer(BlockingQueue<BigInteger> queue) {
            this.queue = queue;
        }
    
        public void run() {
            try {
                BigInteger p = BigInteger.ONE;
                while (!Thread.currentThread().isInterrupted())
                    queue.put(p = p.nextProbablePrime());
            } catch (InterruptedException consumed) {
                /* Allow thread to exit */
            }
        }
    
        public void cancel() {
            interrupt();
        }
    }

    2.中断策略

      由于每个线程拥有各自的中断策略,因此除非弥你知道中断对该线程的含义,否则就不应该中断这个线程。 

    3.响应中断

    4.示例:计时运行

    5.通过Future来实现取消

    6.处理不可中断的阻塞

    二.停止基于线程的服务

  • 相关阅读:
    各种排序算法的时间复杂度和空间复杂度
    fork/join框架
    全文检索之solr学习
    【设计模式最终总结】概述、分类、原则
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(75)-微信公众平台开发-用户管理
    下拉列表自己封装的
    下拉列表
    一个原生的JavaScript拖动方法
    JavaScript的jsonp
    angular2 的依赖注入
  • 原文地址:https://www.cnblogs.com/wuwuyong/p/14270414.html
Copyright © 2011-2022 走看看