start启动单个线程,每次新建开销大且难管控;threadpoolexecutor复用线程池,高效可控,支持排队、拒绝策略与动态调度。

start 方法启动的是单个独立线程,而 ThreadPoolExecutor 管理的是复用的线程集合;前者每次调用都新建线程(开销大、难管控),后者通过预设策略调度任务到已有或按需创建的线程上(高效、可控)。
start 是一次性线程启动入口
调用 Thread.start() 会触发 JVM 创建一个新 OS 线程,并异步执行 run() 中的逻辑。该方法只能调用一次,重复调用抛 IllegalThreadStateException。run() 本身只是普通方法,直接调用不会开启新线程,纯同步执行。
- 每次 start 都涉及系统资源分配(栈内存、上下文切换等),频繁使用易导致性能下降甚至 OOM
- 线程生命周期完全由开发者手动管理:启动、等待、中断、销毁全靠代码控制
- 无内置排队、拒绝、复用机制,适合偶发、简单、隔离性要求高的场景
ThreadPoolExecutor 是任务驱动的线程复用系统
它不直接暴露“启动线程”的概念,而是接收 Runnable/Callable 任务,根据内部状态(核心线程数、队列容量、最大线程数等)决定是立即执行、入队等待,还是扩容线程执行。线程创建后会持续从队列中取任务运行,直到空闲超时或被关闭。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 线程创建成本摊薄:100 个任务可能只用 5 个线程轮流执行,避免反复创建销毁
- 执行顺序受控:任务先进入阻塞队列(如 ArrayBlockingQueue),再按 FIFO 或优先级分发
- 支持拒绝策略(如 CallerRunsPolicy)、可定制线程工厂、存活时间等,应对突发流量更稳健
关键行为对比:任务提交 vs 线程启动
start 是面向“线程实体”的操作;ThreadPoolExecutor.execute() 是面向“任务”的操作。前者关注“谁来跑”,后者关注“让谁跑、何时跑、怎么跑”。例如:
- new Thread(() -> System.out.println("hello")).start(); → 立即起一个新线程打印
- pool.execute(() -> System.out.println("hello")); → 把打印任务交给线程池,由它决定由哪个已有线程执行,或是否新建线程
- 若线程池已满且队列已满,execute 可能触发拒绝策略;而 start 永远尝试新建——失败则直接抛异常
实际选型建议
单次、短时、逻辑简单且无需协调的任务,可用 Thread + start;高频、批量、需限流/监控/复用的业务(如 Web 请求处理、定时任务、IO 回调),必须用 ThreadPoolExecutor(不推荐 Executors 工厂方法,应直接 new,以便显式控制队列类型与大小)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










