线程池里每个线程的名字、daemon、异常处理和上下文,都是由 ThreadFactory 与线程第一次被创建时的环境决定的。这篇逐项量出:哪些属性继承、哪些不继承,异常去哪了,上下文是什么时候被固定的,以及线程什么时候才真正创建。
main 线程里 new Thread:Thread-0(daemon=false, prio=5) 在 daemon 线程里 new Thread:Thread-2(daemon=true, prio=5);在 daemon 线程里用 defaultThreadFactory:pool-1-thread-1(daemon=false, prio=5) 在优先级 9 的线程里 new Thread:Thread-4(daemon=false, prio=9) 固定线程池 2 个线程的默认名字:[pool-2-thread-1(daemon=false, prio=5) 组 main, pool-2-thread-2(daemon=false, prio=5) 组 main]
submit:handler 没有被调用;Future.get() 抛 ExecutionException(submit 里的异常) 第二个任务在 worker-1 上运行 handler 收到:线程 worker-1,异常 execute 里的异常 execute 抛异常之后的任务在 worker-2 上运行 ThreadFactory 一共创建了 2 个线程
池线程(由 submitter 线程第一次提交时创建)的 context ClassLoader = custom-loader,InheritableThreadLocal = submitter-的值 main 线程现在的 context ClassLoader = AppClassLoader(app),InheritableThreadLocal = main-的值;main 再提交任务也不会更新池线程的这两个值
exit-nondaemon:输出 "main 结束,没有 shutdown(非 daemon 线程池)";5 秒后 JVM 仍未退出(被杀掉) exit-daemon:输出 "main 结束,没有 shutdown(daemon 线程池)";JVM 在 0.1 s 内退出,退出码 0
new ThreadPoolExecutor(2, 4, 队列 2):构造后 ThreadFactory 调用 0 次(线程是惰性创建的) 连续提交 6 个阻塞任务:第 1 个任务后 1 次,第 2 个任务后 2 次,第 3 个任务后 2 次,第 4 个任务后 2 次,第 5 个任务后 3 次,第 6 个任务后 4 次 任务结束 500 ms 后(keepAlive 100 ms,默认不回收核心线程):池大小 2,ThreadFactory 累计 4 次 allowCoreThreadTimeOut(true) 后再等 500 ms:池大小 0 虚拟线程:ThreadFactory 生成的名字 vt-0、vt-1,isDaemon() = true,isVirtual() = true,setPriority(10) 之后 getPriority() = 5;setDaemon(false) 会抛 IllegalArgumentException:'false' not legal for virtual threads