java中start()方法在自定义线程池中仅在worker初始化时调用一次,后续任务均由已启动的worker线程复用执行run(),重复调用start()会抛出illegalthreadstateexception。

Java 中 start() 方法在自定义线程池中根本不会被调用。
线程池不使用 start() 启动线程
自定义线程池(如继承 ThreadPoolExecutor 或手动实现)内部管理的是复用的 Worker 线程,这些线程在初始化时已通过 start() 启动过一次。后续任务提交后,线程池不会为每个任务新建线程并调用 start(),而是让已有 Worker 线程从任务队列中获取新任务,在其已运行的线程上下文中直接执行 run() 方法(即任务的 Runnable.run())。
- Worker 类通常继承自
AbstractQueuedSynchronizer,自身封装了一个Thread实例;该Thread在 Worker 构造时就已调用start()—— 这是唯一一次。 - 之后所有任务都由这个长期存活的线程循环执行:
while (task != null || (task = getTask()) != null) { task.run(); } - 调用
execute()或submit()只是把任务加入阻塞队列,触发已有 Worker 唤醒或创建新 Worker(此时才可能触发一次start()),而非每次任务都调用start()。
start() 只在 Worker 初始化时发生
当你调用 new ThreadPoolExecutor(...) 并首次提交任务时,若当前线程数低于 corePoolSize,线程池会创建新 Worker 对象,并在其构造过程中启动底层线程:
-
addWorker()→ 创建Worker实例 → 构造器中执行thread.start() - 此后该线程持续运行,不断从队列取任务、执行
task.run(),不再依赖start() - 线程复用意味着:一个线程可执行成百上千个不同任务,但
start()至多调用一次
为什么不能也不该在线程池里手动调用 start()
显式对线程池中的线程对象调用 start() 会导致 IllegalThreadStateException:
- Worker 内部的
Thread实例一旦进入RUNNABLE或更高状态,再次调用start()就非法 - 线程池自行控制生命周期(如
allowCoreThreadTimeOut、shutdown()),手动干预会破坏状态一致性 - 任务调度由
getTask()和循环体控制,与start()完全解耦
对比:普通 Thread vs 线程池 Worker
区别不在语法,而在执行模型:
-
普通线程:每次
new Thread(r).start()→ 新线程、新调用栈、一次start()→ 执行完r.run()即终止 -
线程池 Worker:一次
start()启动长期线程 → 持续拉取任务 → 多次执行不同run()→ 显式关闭前不退出
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











