线程池的不正确使用引发的问题

线程池的不正确使用引发的问题

public static void main(String[] args) throws InterruptedException {
        Cache cache = new Cache(() -> {
            TimeUnit.SECONDS.sleep(2);
            return 0l;
        }, 3, ChronoUnit.SECONDS);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
        for (int i = 0; i < 20; i++) {
            System.out.println("提交"+i);
            executor.submit(() -> {
                System.out.println(Thread.currentThread().getName() + ">>>>" + cache.get());
            });
        }
        System.out.println("提交完成");
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        System.out.println("over");
    }

描述:
使用线程池来执行任务,配置如下:
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 5, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
执行了20个任务,始终没有看到<<提交完成>>,而且程序一直没有退出。

分析:
核心线程数是2,所以一开始会创建2个线程,使用ArrayBlockingQueue,边界为10,后来又创建了3个线程,这个时候如果在提交新的任务,就会执行拒绝策略,而默认的RejectHandler是AbortPolicy,是直接抛出异常,此时主线程已经中止了,无法执行shutdown操作。主线程中止了,但是为什么进程没有退出?是因为此时线程池里面的线程还没有回收,在存在非守护线程的情况下,jvm进程没法退出。过了半个小时,进程仍然没有退出,是因为core的值是2,也就是线程池会从5个线程回收到2个,但是会仍然存在两个线程的,所以一直无法退出。

修正:

  1. 更换拒绝策略,保证程序会执行到shutdown
  2. 修改核心线程数为0,保证抛出异常后,线程池会把所有执行完的线程回收,jvm进程自动退出

你可能感兴趣的:(线程池的不正确使用引发的问题)