Java多线程 停止线程遇到线程阻塞如何处理?

文章目录

        • 线程可能被阻塞
        • 如果线程在每次迭代时都阻塞

线程可能被阻塞

子线程sleep的过程中, 给出中断信号的demo

当子线程正在休眠的过程中, 去进行线程的中断.
因此主线程要等子线程执行到 Thread.sleep(1000);这一行代码,因此在main线程中, 给出了Thread.sleep(500);

public class RightWayStopThreadWithSleep {


    public static void main(String[] args) throws InterruptedException {

        // 创建线程任务
        Runnable runnable = () -> {
            int num = 0;
            try {
                while (num <= 300 && !Thread.currentThread().isInterrupted()) {
                    if (num % 100 == 0) {
                        System.out.println(num + " 是100的整数");
                    }
                    num++;
                }

                //执行完成循环累加后, 执行sleep, 此时主线程给出中断信号
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        };

        //启动线程
        Thread thread = new Thread(runnable);

        thread.start();

        //当子线程 正在休眠的过程中, 去进行线程的中断.
        //因此要等子线程执行到  Thread.sleep(1000);这一行代码
        //此处的  Thread.sleep(500); 是给子线程  循环0到300的时间用的
        Thread.sleep(500);

        //子线程执行完成0到300累加后, 在子线程sleep的过程中, 去给出中断的信号
        thread.interrupt();
    }
}

程序执行的结果如下 :
Java多线程 停止线程遇到线程阻塞如何处理?_第1张图片
可以看到 当子线程执行完循环的任务后 ,响应主线程的中断信号的方式为 抛出异常.
那是因为在子线程中, sleep方法被try catch所包裹了,
面对在sleep中,这种类似的阻塞操作的时候, 就会catch出这个异常, 打印如下的异常 ,响应中断
java.lang.InterruptedException: sleep interrupted
通过断点调试可以看到, 进入了catch的代码块.
Java多线程 停止线程遇到线程阻塞如何处理?_第2张图片

而如果子线程没有阻塞的状态, 那么子线程即使收到了中断的信号, 也不会抛出异常.

如果线程在每次迭代时都阻塞

线程在每次迭代时都阻塞的代码如下. 在子线程循环的过程中, 每次都Thread.sleep(10); 休眠10ms.
在子线程运行5s,后, 主线程给子线程发出中断的通知.

public class RightWayStopThreadWithSleepEveryLoop {

    public static void main(String[] args) throws InterruptedException {

        // 创建线程任务
        Runnable runnable = () -> {
            int num = 0;
            try {
                while (num <= 10000 && !Thread.currentThread().isInterrupted()) {
                    if (num % 100 == 0) {
                        System.out.println(num + " 是100的整数");
                    }
                    num++;
                    //每一次循环,休眠10ms
                    Thread.sleep(10);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        //启动线程
        Thread thread = new Thread(runnable);
        thread.start();

        //此处的  Thread.sleep(5000); 是休眠主线程, 让子线程运行5s,
        //子线程运行5s后, 给出子线程的休眠信号
        Thread.sleep(5000);
        thread.interrupt();
    }
}

此时打印如下. 子线程打印出来sleep过程中被中断的异常
Java多线程 停止线程遇到线程阻塞如何处理?_第3张图片
与上一节线程可能被阻塞的区别是, 此时由于每一次的循环,都会sleep, 因此真正判断子线程是否被中断, 不是使用Thread.currentThread().isInterrupted(), 而是在Thread.sleep(10); 休眠的过程中, 就能立刻的感知到了中断通知, 就会抛出异常.
因此可以把代码修改如下, 在子线程的while (num <= 10000) 时, 就不需要进行判断线程是否中断了.

public class RightWayStopThreadWithSleepEveryLoop {


    public static void main(String[] args) throws InterruptedException {

        // 创建线程任务
        Runnable runnable = () -> {
            int num = 0;
            try {
                while (num <= 10000) {
                    if (num % 100 == 0) {
                        System.out.println(num + " 是100的整数");
                    }
                    num++;
                    //每一次循环,休眠10ms
                    Thread.sleep(10);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };
        //启动线程
        Thread thread = new Thread(runnable);
        thread.start();

        //此处的  Thread.sleep(5000); 是休眠主线程, 让子线程运行5s,
        //子线程运行5s后, 给出子线程的休眠信号
        Thread.sleep(5000);
        thread.interrupt();
    }

}

打印的结果如下. 与加上判断线程是否中断的一致.
Java多线程 停止线程遇到线程阻塞如何处理?_第4张图片
因此, 只要子线程在while循环的过程中, 每一次循环都会有让线程进行阻塞一段时间的情况下, 就不需要加上线程是否被中断的条件判断 .
因为会在阻塞的过程中,检测中断的状态, 并且抛出异常

你可能感兴趣的:(Java多线程基础与核心)