Java多线程-线程池ExecutorService.shutdown什么时候执行

时间:2022-06-15 18:36:22
ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭。
但是我用了计数信号量Semaphore后,发现线程还没有跑完,他就执行了shutdown().
各位大虾帮忙解答一下 Java多线程-线程池ExecutorService.shutdown什么时候执行



public class SemaphoreTest extends Thread {
    Semaphore position;
    private int id;
    public SemaphoreTest(int i, Semaphore s) {
        this.id = i;
        this.position = s;
    }
    public void run() {
        try {
            if (position.availablePermits() > 0) {
                System.out.println("顾客[" + id + "]进入厕所,有空位");
            } else {
                System.out.println("顾客[" + id + "]进入厕所,没空位,排队");
            }
            position.acquire(); 
            System.out.println("【" + id + "】acquire坑位");
            Thread.sleep((int) (Math.random() * 1000));
            System.out.println("【" + id + "】完毕release");
            position.release(); 
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        ExecutorService pool = Executors.newCachedThreadPool();
        Semaphore position = new Semaphore(2);    // 初始化两个空位
        for (int i = 0; i < 5; i++) {
            pool.submit(new SemaphoreTest(i, position));
        }
        System.out.println("开始释放线程池资源");
        pool.shutdown();
        System.out.println("完成释放线程池资源");
        position.acquireUninterruptibly(2);  
        System.out.println("如厕完毕,清理厕所");
        position.release(2);  
    }
}

4 个解决方案

#1


你的代码中,主线程并没有等待线程池执行完毕这一说啊,当然是持续往下执行了。。。

至于你的信号量,从代码来看,只会在几个子线程之间发挥作用。

#2


引用 1 楼 ldh911 的回复:
你的代码中,主线程并没有等待线程池执行完毕这一说啊,当然是持续往下执行了。。。

至于你的信号量,从代码来看,只会在几个子线程之间发挥作用。


【主线程并没有等待线程池执行完毕】
这个是什么意思呢?主线程和线程池什么什么关系啊?他们的生命周期有没有什么关联?
另外,ExecutorService.shutdown()这个方法,是什么时候执行的?看手册描述得还是有点模糊……
谢谢大虾了!! Java多线程-线程池ExecutorService.shutdown什么时候执行

#3


主线程和线程池之间没有直接关系,线程池使用自己的线程。生命周期也相互独立。

shutdown()可以理解为:主线程要求线程池关闭,但不会为此等待线程池执行完毕。你这里面实际发挥了等待作用的并不是线程池所提供的能力(当然线程池也确实提供了这类能力),而是:position.acquireUninterruptibly(2) 这句话。


shutdown() 作为函数,当然是立即执行,也即是不再接受新任务了; 但是它即不会强行终止正在执行的任务,也不会取消已经提交的任务。也就是说之前提交的5个任务,仍然会执行完毕,且跟主线程生命周期无关,也就是即便你直接在后面写上: if (1==1) return; 来立即结束主函数,你也会发现线程池的5个任务会顺利执行完毕。


另一个长得很像的函数是:
shutdownNow(),这个函数比shutdown()更狠,两点:
1、对于尚未执行的任务,全部取消掉;
2、对于正在执行的任务,发出interrupt()。
不过你的程序因为在发生异常时没有正确释放信号量,所以如果改为shutdownNow()会出问题:主线程死等。

#4


受教了,大虾果然功力深厚 Java多线程-线程池ExecutorService.shutdown什么时候执行

#1


你的代码中,主线程并没有等待线程池执行完毕这一说啊,当然是持续往下执行了。。。

至于你的信号量,从代码来看,只会在几个子线程之间发挥作用。

#2


引用 1 楼 ldh911 的回复:
你的代码中,主线程并没有等待线程池执行完毕这一说啊,当然是持续往下执行了。。。

至于你的信号量,从代码来看,只会在几个子线程之间发挥作用。


【主线程并没有等待线程池执行完毕】
这个是什么意思呢?主线程和线程池什么什么关系啊?他们的生命周期有没有什么关联?
另外,ExecutorService.shutdown()这个方法,是什么时候执行的?看手册描述得还是有点模糊……
谢谢大虾了!! Java多线程-线程池ExecutorService.shutdown什么时候执行

#3


主线程和线程池之间没有直接关系,线程池使用自己的线程。生命周期也相互独立。

shutdown()可以理解为:主线程要求线程池关闭,但不会为此等待线程池执行完毕。你这里面实际发挥了等待作用的并不是线程池所提供的能力(当然线程池也确实提供了这类能力),而是:position.acquireUninterruptibly(2) 这句话。


shutdown() 作为函数,当然是立即执行,也即是不再接受新任务了; 但是它即不会强行终止正在执行的任务,也不会取消已经提交的任务。也就是说之前提交的5个任务,仍然会执行完毕,且跟主线程生命周期无关,也就是即便你直接在后面写上: if (1==1) return; 来立即结束主函数,你也会发现线程池的5个任务会顺利执行完毕。


另一个长得很像的函数是:
shutdownNow(),这个函数比shutdown()更狠,两点:
1、对于尚未执行的任务,全部取消掉;
2、对于正在执行的任务,发出interrupt()。
不过你的程序因为在发生异常时没有正确释放信号量,所以如果改为shutdownNow()会出问题:主线程死等。

#4


受教了,大虾果然功力深厚 Java多线程-线程池ExecutorService.shutdown什么时候执行