zoukankan      html  css  js  c++  java
  • 一个关于ExecutorService shutdownNow时很奇怪的现象

    我们知道很多类库中的阻塞方法在抛出InterruptedException后会清除线程的中断状态(例如 sleep、 阻塞队列的take),但是今天却发现了一个特别奇怪的现象,先给出代码:

        public static void main(String[] args) throws InterruptedException {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        TimeUnit.SECONDS.sleep(10);
                    } catch (InterruptedException e) {
                        System.out.println("first interrupted!!!");
                    }
                    
                    System.out.println(Thread.currentThread().isInterrupted());
                    
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        System.out.println("second interrupted!!!");
                    }
                }
            });
            
            executor.shutdownNow();
        }

     如果按照我的理解,调用shutdownNow后会给线程池中的工作者线程发出中断请求,并在第一个睡眠的地方抛出 InterruptedException ,但是在抛出异常后这种中断状态就应该被清除了,所以第二次睡眠不应该失败,但是结果却是失败的,本来以为是系统的原因,可是在linux下测试也是如此。

    更令人不解的是如果我把第二次睡眠换成其他的阻塞方法(queue.take)那么就不会抛出异常,而是正常阻塞。 

        public static void main(String[] args) throws InterruptedException {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            final BlockingQueue<String> queue = new LinkedBlockingQueue<>();
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        TimeUnit.SECONDS.sleep(10);
                    } catch (InterruptedException e) {
                        System.out.println("first interrupted!!!");
                    }
                    
                    System.out.println(Thread.currentThread().isInterrupted());
                    
                    try {
                        queue.take();
                    } catch (InterruptedException e) {
                        System.out.println("second interrupted!!!");
                    }
                }
            });
            
            executor.shutdownNow();
        }

     还有更让人受不了的,如果我们在任务最开始随便写点什么,就会按照我们期待的执行了(心中一万只草泥马呀)

        public static void main(String[] args) throws InterruptedException {
            ExecutorService executor = Executors.newSingleThreadExecutor();
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("xxxx");
                    try {
                        TimeUnit.SECONDS.sleep(10);
                    } catch (InterruptedException e) {
                        System.out.println("first interrupted!!!");
                    }
                    
                    System.out.println(Thread.currentThread().isInterrupted());
                    
                    try {
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        System.out.println("second interrupted!!!");
                    }
                }
            });
            
            executor.shutdownNow();
        }

    以后有机会再研究吧,可能还是知识不够吧!!!!

  • 相关阅读:
    Js常用的函数
    数组和集合的相互转换
    Java中的volatile的作用和synchronized作用
    mac下使用mysql控制台命令行
    几种优化ajax的执行速度的方法
    解决Macbook网络连接成功但是图标一直显示正在查找网络问题
    Android Stdio 中的Rendering Problems Android N requires the IDE to be running with Java 1.8 or later Install a supported JDK解决办法
    Activiti 中的ACT_RU_TASK表中的EXECUTION_ID和PROC_INST_ID区别
    Ibatis学习总结2--SQL Map XML 配置文件
    Ibatis学习总结1--ibatis简介和SQL Maps
  • 原文地址:https://www.cnblogs.com/zh1164/p/7079657.html
Copyright © 2011-2022 走看看