• 运行停止一个线程


    并发概念汇总

    http://www.letiantian.me/2015-05-27-java-concurrency-summary/

    并发的系统文章

    http://www.cnblogs.com/dolphin0520/category/602384.html

    http://www.cnblogs.com/timlearn/tag/Java%E5%B9%B6%E5%8F%91/

    http://blog.csdn.net/ghsau/article/category/1707779

    最简单的java线程池与任务队列

    http://www.cnblogs.com/null7/archive/2012/09/20/2696108.html

    中断机制

    http://www.cnblogs.com/timlearn/p/4008783.html

    一.运行一个线程

      运行一个线程的方法十分简单,我们只需调用Thread实例的start()方法即可,当我们调用start()方法之后,Java虚拟机会为我们创建一个线程,然后在该线程中运行run()方法中定义的任务,真正实现多线程。

        在这里,必须强调的是应该调用start()方法,而不是run()方法,直接调用run()方法,虚拟机不会新建线程运行任务,只会在当前线程执行任务,无法实现多线程并发,所以应该调用start()方法。

    二.停止一个线程

    (1)标志位方法

      在任务中定义一个标志位,然后任务会定期查看标志位,如果设置了标志位,则任务结束。注意,标志位必要设置为volatile类型。

    我们使用这项技术来枚举素数。

    public class PrimeGenerator implements Runnable {
        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);
        }
    }
    

     当cancel()方法调用后,while就会结束,整个线程也会结束。

    (2)使用中断停止线程

      在(1)中的使用标志位的方法中,有一个问题,如果线程的任务是阻塞任务,那么线程在阻塞时将无法去查看标志位,因此也无法停止。

      当出现这种情况时,我们可以使用中断,有部分阻塞库方法是支持中断的,线程中断是一个协作机制,线程可以通过这种机制来通知另一个线程,告诉它在合适或者可能的情况下停止当前的工作,

    并转而执行其它的工作。

      修改上面的ArrayList为BlockingQueue,BlockingQueue的put()是可以阻塞的,如果还使用标志位的方法,那么当put阻塞后,将无法再执行while判断,这时我们就可以使用中断标志位的方法来判断结束线程。,

    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();//Thread.interrupt()
        }
    }
    

       这时,我们注意到,cancel()调用时,设置了当前线程的中断标志位为true,BlockingQueue的put()方法可以响应中断,并从阻塞状态返回,返回后,while语句检测到中断位被标志,然后结束整个while

    循环,从而结束线程。

    (3)不能响应中断的阻塞方法

      如果阻塞方法可以响应中断,我们就可以使用(2)中的方法结束线程,但是还有一些阻塞方法不能响应中断。这里就要通过关闭底层资源,让代码throw异常的方式来结束线程。(略)

     

     

  • 相关阅读:
    适配器模式
    快排变种
    美团面试问题
    gulp前端自动化构建工具新手入门篇
    javascript继承
    .call()和.apply()相同点与不同点
    JavaScript原型,原型链 !
    锚点链接和hash属性
    构造函数与普通函数的比较
    JS的作用域和作用域链
  • 原文地址:https://www.cnblogs.com/chuiyuan/p/5205006.html
Copyright © 2020-2023  润新知