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