【并发编程】线程池是否需要手动关闭吗?以Hutool中的线程池为例

Hutool工具包中使用线程池的API是:

  ThreadUtil.execute()

    /**
     * 直接在公共线程池中执行线程
     *
     * @param runnable 可运行对象
     */
    public static void execute(Runnable runnable) {
        GlobalThreadPool.execute(runnable);
    }

  内部使用的一个名为 GlobalThreadPool的线程池,该线程池使用ExecutorBuilder建造者模式去创建,其线程池的默认参数如下:

public class GlobalThreadPool {
    private static ExecutorService executor;

    private GlobalThreadPool() {
    }

    static {
        init();
    }

    /**
     * 初始化全局线程池
     */
    synchronized public static void init() {
        if (null != executor) {
            executor.shutdownNow();
        }
        executor = ExecutorBuilder.create().useSynchronousQueue().build();
    }
    private static final long serialVersionUID = 1L;

    /** 默认的等待队列容量 */
    public static final int DEFAULT_QUEUE_CAPACITY = 1024;

    /**
     * 初始池大小
     */
    private int corePoolSize;
    /**
     * 最大池大小(允许同时执行的最大线程数)
     */
    private int maxPoolSize = Integer.MAX_VALUE;
    /**
     * 线程存活时间,即当池中线程多于初始大小时,多出的线程保留的时长
     */
    private long keepAliveTime = TimeUnit.SECONDS.toNanos(60);
    /**
     * 队列,用于存在未执行的线程
     */
    private BlockingQueue<Runnable> workQueue;
    /**
     * 线程工厂,用于自定义线程创建
     */
    private ThreadFactory threadFactory;
    /**
     * 当线程阻塞(block)时的异常处理器,所谓线程阻塞即线程池和等待队列已满,无法处理线程时采取的策略
     */
    private RejectedExecutionHandler handler;
    /**
     * 线程执行超时后是否回收线程
     */
    private Boolean allowCoreThreadTimeOut;

  可以看到其corePoolSize线程数是0,最大线程数是Integer.max_value,也就是21亿,线程最大存活时间为60s,下面为测试Demo

public class Test {

    public static void main(String[] args) throws Exception {
        final AtomicReference<BigDecimal> REFERENCE = new AtomicReference<>();
        final AtomicInteger atomicInteger =new AtomicInteger();
        CountDownLatch countDownLatch = ThreadUtil.newCountDownLatch(500);
        for (int i = 0; i < 500; i++) {
            final int a = i;
            ThreadUtil.execute(() -> {
                atomicInteger.incrementAndGet();
                System.out.println("线程" + a);
                REFERENCE.set(BigDecimal.valueOf(a));
                countDownLatch.countDown();
            });
        }
        countDownLatch.await();
        System.out.println("===== Atomic ====="+atomicInteger.get());
        System.out.println("=====SUCCEED=====" + REFERENCE.get());

    }
}

  测试demo可以看到主线程执行完毕后,程序并不会中止,因为子线程仍然存活,60s后程序终止;

因此这里有个结论:

  1.线程池corePoolSize为0,且最大线程数设置为存活时间,则可以不用关闭线程池,特别是在请求比较密集的情况下,能更好的减少创建线程所需要的时间

  2.如果核心线程数较多,且最大线程数的存活时间较长,请求量不大,则可以手动关闭线程池,减少线程长期存在的性能损耗;

 

原文地址:https://www.cnblogs.com/july-sunny/p/12759265.html