Java 多线程(二):如何正确的停止一个线程

1. 什么是停止线程

停止一个线程意味着在任务处理完任务之前停掉正在做的操作,也就是放弃当前的操作。

2. 错误的方式 - 调用Thread.stop()方法

虽然停止一个线程可以用Thread.stop()方法,但最好不要用它。它确实可以停止一个正在运行的线程,但是这个方法是不安全的,而且是已被废弃的方法。使用这个方法可能会导致数据出现破坏,甚至导致程序的流程出现错误。

3. 如何正确的停止线程

有以下2种方法可以终止正在运行的线程:

1). 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

2). 使用interrupt方法中断线程。

4. 使用退出标志退出线程

我们可以使用volatile修饰的boolean标识位的方式来停止线程:

public class InterruptThread {

    public static void main(String[] args) throws InterruptedException {
        InterruptableThread interruptableThread = new InterruptableThread();
        interruptableThread.start();
        Thread.sleep(6);
        interruptableThread.isStopped = true;
    }


    static class InterruptableThread extends Thread {

        public volatile boolean isStopped = false;

        @Override
        public void run() {
            super.run();
            for (int i = 0; i < 10000000 ; i++) {
                if (isStopped) {
                    System.out.println("i = " + i);
                    return;
                }
            }
        }
    }
}

 输出内容:

i = 1647062

可以看到循环遍历并没有执行完,就停止了,说明此方式能够做到退出线程。这里使用volatile修饰是为了防止因为多线程访问同一字段出现可见性的问题。

5.  使用 Thread.interrupt() 方法停止线程 

使用interrupt()方法的使用效果并不像for+break语句那样,马上就停止循环。调用interrupt方法是在当前线程中打了一个停止标志,并不是真的停止线程。

下面我们举两个例子,都是使用了interrupt()方法,但是一个不能够停止线程执行,另一个就能停止线程执行。

如下面的代码,即使我们调用了interrupt(),线程也不会停止执行:

public class MyThread extends Thread {
    public void run(){
        super.run();
        for(int i=0; i<500000; i++){
            System.out.println("i="+(i+1));
        }
    }
}

public class Run {
    public static void main(String args[]){
        Thread thread = new MyThread();
        thread.start();
        try {
            Thread.sleep(2000);
            thread.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

其输出结果:

...
i=499994
i=499995
i=499996
i=499997
i=499998
i=499999
i=500000

 使用interrupt()方法,能够终止线程的执行的正确方式如下:

public class MyThread extends Thread {
    public void run(){
        super.run();
        for(int i=0; i<500000; i++){
            if(this.interrupted()) {
return; } System.out.println("i="+(i+1)); } } } public class Run { public static void main(String args[]){ Thread thread = new MyThread(); thread.start(); try { Thread.sleep(2000); thread.interrupt(); } catch (InterruptedException e) { e.printStackTrace(); } } }

运行结果如下:

...
i=202053
i=202054
i=202055
i=202056

6. 判断线程是否停止的方法

Thread方法提供了两个方法来判断线程是否停止:interrupted()、isInterrupted()。

interrupted()是静态方法:内部实现是调用的当前线程的isInterrupted(),并且会重置当前线程的中断状态。

isInterrupted()是实例方法,是调用该方法的对象所表示的那个线程的isInterrupted(),不会重置当前线程的中断状态。

 

posted @ 2020-06-17 12:50  灰色飘零  阅读(766)  评论(2)    收藏  举报