美文网首页
Java Thread 安全退出

Java Thread 安全退出

作者: PC8067 | 来源:发表于2021-07-05 16:57 被阅读0次
    package com.pc.screenproject;
    
    public class Test {
    
        private static boolean isStop = false;
    
        /**
         * 自定义退出标识isStop
         * Before : isStop=false
         * After : isStop=true
         */
        private static void test0() {
            isStop = false;
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("测试自定义退出标识isStop用法");
                    System.out.println("Before : isStop=" + isStop);
                    while (!isStop) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("After : isStop=" + isStop);
                }
            });
            t.start();
    
            try {
                Thread.sleep(500);
                isStop = true;
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 非阻塞状态下
         * Thread.currentThread().isInterrupted() : 获取中断标志位,调用不会清空中断标志位;
         * 运行结果
         * Before : false
         * After : true
         */
        private static void test1() {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("测试非阻塞状态下isInterrupted用法");
                    System.out.println("Before : " + Thread.currentThread().isInterrupted());
                    while (!Thread.currentThread().isInterrupted()) {
                        ;
                    }
                    System.out.println("After : " + Thread.currentThread().isInterrupted());
                }
            });
            t.start();
    
            try {
                Thread.sleep(500);
                t.interrupt();
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 非阻塞状态下
         * Thread.interrupted() : 获取中断标志位,调用一次就立即清空中断标志位;
         * 运行结果
         * Before : false
         * After : false
         */
        private static void test2() {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("测试非阻塞状态下interrupted用法");
                    System.out.println("Before : " + Thread.currentThread().isInterrupted());
                    while (!Thread.interrupted()) {
                        ;
                    }
                    System.out.println("After : " + Thread.currentThread().isInterrupted());
                }
            });
            t.start();
            try {
                Thread.sleep(500);
                t.interrupt();
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 阻塞状态下
         * sleep() : 抛出InterruptedException后中断标志位被清除,所以循环无法退出。标准做法是
         *      1. 再次调用interrupt恢复中断;
         *      2. 直接break退出;
         * 运行结果
         * Before : false
         * After : false
         */
        private static void test3() {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("测试sleep阻塞状态下中断用法");
                    System.out.println("Before : " + Thread.currentThread().isInterrupted());
                    while (!Thread.interrupted()) {
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
    //                        break;
                        }
                    }
                    System.out.println("After : " + Thread.currentThread().isInterrupted());
                }
            });
            t.start();
            try {
                Thread.sleep(500);
                t.interrupt();
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            test0();
            test1();
            test2();
            test3();
        }
    }
    

    线程安全退出总结:

    1. 自定义停止标识;如test0()
    2. 通过interrupt()函数,这里分为两种情况:
      • 非阻塞情况,则通过Thread.interrupted()或者Thread.currentThread().isInterrupted()
      • 阻塞情况,一般会抛出InterruptedException异常,则需要在 try...catch再次执行Thread.currentThread().interrupt()或者break,否则循环无法退出。
    3. InterruptedException异常会清除中断标识位,此时通过Thread.interrupted()或者Thread.currentThread().isInterrupted()查看则都为false
    4. 捕获到InterruptedException异常之后,需要通过Thread.currentThread().interrupt()再次设置一下中断标识位,才能保证中断标识位正常;
    5. Thread.interrupted()Thread.currentThread().isInterrupted()的区别在于,Thread.currentThread().isInterrupted()不改变中断标识位,而Thread.interrupted()调用之后会重置中断标识位。

    相关文章

      网友评论

          本文标题:Java Thread 安全退出

          本文链接:https://www.haomeiwen.com/subject/eybgultx.html