直接new Thread()不适合高并发场景,因频繁创建销毁线程导致栈内存分配、GC压力、调度竞争及OS线程耗尽;Executor框架通过复用线程、统一管理生命周期、解耦任务提交与执行来优化。

为什么直接 new Thread() 不适合高并发场景
频繁创建和销毁线程会带来显著的系统开销:JVM 需要分配栈内存、触发 GC、参与线程调度竞争。在 QPS 较高的服务中,new Thread(runnable).start() 很快会耗尽 OS 线程资源(Linux 默认每进程约 1024 个线程),抛出 java.lang.OutOfMemoryError: unable to create new native thread。
Executor 框架通过复用线程、统一管理生命周期、解耦任务提交与执行,把“怎么跑”交给线程池,“跑什么”由业务代码决定。
- 线程池不是万能的——它只缓解线程创建成本,不解决任务内部阻塞、死锁或共享状态竞争
-
Executors工具类创建的线程池有陷阱:比如Executors.newFixedThreadPool(n)底层用的是无界LinkedBlockingQueue,任务堆积会导致 OOM - 生产环境推荐显式构造
ThreadPoolExecutor,明确控制核心线程数、队列容量、拒绝策略
ThreadPoolExecutor 的几个关键参数怎么设才合理
核心不是背参数名,而是理解它们如何协同影响吞吐与稳定性。以 Web 请求处理为例:
-
corePoolSize:常驻线程数,建议设为 CPU 核心数 × (1 + 平均等待时间 / 平均执行时间),IO 密集型可适当放大 -
maximumPoolSize:最大线程数,避免设得过大(如 1000+),否则上下文切换开销反超收益;一般不超过corePoolSize × 2 -
workQueue:优先选有界队列,如ArrayBlockingQueue(100);避免SynchronousQueue在突发流量下直接触发拒绝策略 -
handler:别用默认的AbortPolicy(直接抛RejectedExecutionException);更稳妥的是CallerRunsPolicy(让调用线程自己执行任务,自然降速)或自定义记录+告警
ThreadPoolExecutor executor = new ThreadPoolExecutor(
4, // corePoolSize
8, // maximumPoolSize
60L, // keepAliveTime
TimeUnit.SECONDS,
new ArrayBlockingQueue(100),
new ThreadPoolExecutor.CallerRunsPolicy()
);
submit() 和 execute() 的区别不只是返回值
execute(Runnable) 是 Executor 接口方法,只负责提交,不关心结果;submit() 是 ExecutorService 扩展方法,支持获取执行结果和异常。
立即学习“Java免费学习笔记(深入)”;
Android 是一个专门针对移动设备的软件集,它包括一个操作系统,中间件和一些重要的应用程序。Beta版的 Android SDK 提供了在Android平台上使用JaVa语言进行Android应用开发必须的工具和API接口。 特性 应用程序框架 支持组件的重用与替换 Dalvik 虚拟机 专为移动设备优化 集成的浏览器 基于开源的WebKit 引擎 优化的图形库 包括定制的2D图形库,3D图形库基于
- 用
submit(Runnable)时,返回的Future调用get()只会返回null,但能捕获运行时异常(比如空指针) - 用
submit(Callable才真正发挥异步计算价值:) Futuref = executor.submit(() -> "done"); String result = f.get(); - 注意
Future.get()是阻塞的;若需非阻塞,可用isDone()轮询,或结合CompletableFuture做链式回调 - 忘记调用
get()或未处理ExecutionException,会导致异常“静默丢失”
线程池 shutdown() 和 shutdownNow() 到底停不停得干净
两者都不保证立即终止所有线程,只是改变线程池状态并尝试中断正在运行的任务。
-
shutdown():设置RUNNING → SHUTDOWN,不再接受新任务,但会等已提交任务(包括队列中等待的)全部执行完 -
shutdownNow():设置RUNNING → STOP,尝试中断所有正在执行的线程,并清空队列,返回未执行的任务列表 - 真正“停干净”的关键是任务自身响应中断:必须在循环中检查
Thread.interrupted()或捕获InterruptedException,否则shutdownNow()对该线程无效 - 典型错误写法:
while (true) { doWork(); }—— 它永远不响应中断;应改为while (!Thread.currentThread().isInterrupted()) { doWork(); }
实际关闭流程建议加超时等待:
executor.shutdown();
try {
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
executor.shutdownNow();
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminate");
}
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
线程池的边界往往藏在 shutdown 逻辑里——没等完就退出、没处理中断、没清理资源,都会让应用在重启或降级时留下残留线程。










