多线程中interrupt()详解以及如何结束线程

多线程中sleep(), wait()和interrupt()关系

对于理解interrupt(), 我们最重要的是要清楚interrupt()方法到底是什么作用, 在程序里面到底做了什么!!!
首先下结论:

my.interrupt()方法仅仅只是设置对my线程标记中断状态interrupt status.

提到interrupt()不得不补充一下阻塞, 当线程调用wait() , wait(long) ,或wait(long, int)的方法Object类,或join() , join(long) , join(long, int) , sleep(long) ,或sleep(long, int) 这个类的方法,线程会进入阻塞状态.

—如果A线程调用interrupt()标记中断状态, 当A线程进入阻塞状态时, 线程的interrupt status会被清除,并且将收到一个InterruptedException。
—如果该线程进入阻塞状态后, A线程不占用CPU, 无法调用interrupt()方法, 会抛出InterruptedException。
public class MyThread extends Thread {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 10; i++) {
                //阻塞1秒
                sleep(1000);
                for (int j = 0; j < 100; j++) {
                    System.out.println(System.currentTimeMillis()
                     + Thread.currentThread().getName() + "  " + j);
                }
            }
            //阻塞期间catch异常,
        } catch (InterruptedException e) {
            System.out.println("支线程终止?");
        }
        //其实线程并没有真的停止,try catch外面的for循环会继续
        for (int i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }
}

public class TestDemo01 {
    public static void main(String[] args) throws InterruptedException {
        MyThread my = new MyThread();
        my.start();
        //主线程1.1秒后,执行interrupt();
        Thread.sleep(1100);
        //interrupt()对my线程标记中断状态不影响正在运行的my线程.
        my.interrupt();
        System.out.println("主线程终止");
    }
}

在这里插入图片描述

我们会发现, interrupt()并没有停止线程. interrupt()只是用来标记, 然后通过阻塞手段抛出异常, 跳出当前代码, 进入catch以及后续的代码, 达到类似中止线程的效果.

如下是反例, 没有阻塞和判断, interrupt()就没有任何意义, 代码如下,线程会完成整个循环:

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 1000000; i++) {
            System.out.println(i);
        }
    }
}
public class TestDemo01 {
    public static void main(String[] args) throws InterruptedException {
        MyThread my = new MyThread();
        my.start();
        Thread.sleep(1100);
        my.interrupt();
        System.out.println("主线程终止");
    }
}

consol:
999997
999998
999999
Process finished with exit code 0

那么, 我们到底如何结束线程呢?

上述代码中, 可以在run()中加入判断, 然后通过"return;" 结束线程

public void run() {
    for (int i = 0; i < 1000000; i++) {
        if(i==200){
            return;
        }
        System.out.println(i);
    }
}
public class TestDemo01 {
    public static void main(String[] args) throws InterruptedException {
        MyThread my = new MyThread();
        my.start();
        //Thread.sleep(1100);
        //my.interrupt();
        System.out.println("主线程终止");
    }
}

console:
198
199
主线程终止?

Process finished with exit code 0

但是这样调用者就无法添加interrupt()控制线程.

那么如果没有阻塞, 还有没有其他办法中止线程呢?

Thread.currentThread().isInterrupted(): 测试线程是否已经中断,不会清除interrupt()标记;

通过这个方法判断中断标记, 如果有中断标记,返回true, 没有标记返回flase.

public class MyThread extends Thread {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 1000000; i++) {
                if(Thread.currentThread().isInterrupted()){
                    throw new InterruptedException();
                }
                System.out.println(i);
            }
        } catch (InterruptedException e) {
            System.out.println("支线程终止");
        }
    }
}
public class TestDemo01 {
    public static void main(String[] args) throws InterruptedException {
        MyThread my = new MyThread();
        my.start();
        Thread.sleep(1100);
        my.interrupt();
        System.out.println("主线程终止");
    }
}

consol:
197232
197233
197234
主线程终止?

Process finished with exit code 0

猜你喜欢

转载自blog.csdn.net/weixin_42098099/article/details/84790904
今日推荐