运行停止一个线程

并发概念汇总

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异常的方式来结束线程。(略)

 

 

原文地址:https://www.cnblogs.com/chuiyuan/p/5205006.html