6人参与 • 2026-09-17 • Java
| 问题 | 说明 |
|---|---|
| 频繁创建/销毁线程开销大 | 线程创建涉及系统调用,消耗时间和资源 |
| 线程数量无限制风险 | 大量线程会导致内存溢出、cpu 过度切换 |
| 难以管理 | 缺乏统一的任务调度、取消、优先级控制 |
线程池的核心价值:复用线程、控制并发数、便于管理。
public threadpoolexecutor(
int corepoolsize, // 核心线程数
int maximumpoolsize, // 最大线程数
long keepalivetime, // 非核心线程存活时间
timeunit unit, // 时间单位
blockingqueue<runnable> workqueue, // 任务队列
threadfactory threadfactory, // 线程工厂
rejectedexecutionhandler handler // 拒绝策略
)| 参数 | 作用 | 重点 |
|---|---|---|
corepoolsize | 即使空闲也保留的线程数 | 任务提交后先创建到 core 数量 |
maximumpoolsize | 线程池允许的最大线程数 | 队列满后才创建到 max |
keepalivetime | 非核心线程空闲多久被回收 | 只针对 > corepoolsize 的线程 |
workqueue | 存放待执行任务的阻塞队列 | 高频 |
threadfactory | 创建线程的工厂 | 可自定义线程名、优先级、守护状态 |
handler | 拒绝策略 | 高频 |
提交任务
↓
当前线程数 < corepoolsize?
├── 是 → 创建新线程执行任务
└── 否 → 任务加入 workqueue
↓
队列是否已满?
├── 否 → 排队等待
└── 是 → 当前线程数 < maximumpoolsize?
├── 是 → 创建临时线程执行任务
└── 否 → 执行拒绝策略⚠️ 关键理解:不是先填满队列再创建线程,而是先创建到 core,再填队列,最后再扩容到 max。
| 策略 | 行为 | 适用场景 |
|---|---|---|
abortpolicy(默认) | 直接抛 rejectedexecutionexception | 需要快速失败 |
callerrunspolicy | 由调用线程(主线程)自己执行 | 降低提交速度,自我保护 |
discardpolicy | 静默丢弃任务 | 允许丢任务 |
discardoldestpolicy | 丢弃队列最老的任务,重试提交 | 新任务更重要 |
| 队列类型 | 特点 | 典型使用 |
|---|---|---|
synchronousqueue | 不存储元素,直接移交 | cachedthreadpool,高吞吐 |
linkedblockingqueue | 无界队列(默认 integer.max_value) | fixedthreadpool,可能 oom |
arrayblockingqueue | 有界数组队列,需指定容量 | 生产环境推荐,防止 oom |
priorityblockingqueue | 支持优先级排序 | 任务有优先级时 |
delayedworkqueue | 延迟执行 | scheduledthreadpool 内部使用 |
// 1. 固定线程数 executorservice fixed = executors.newfixedthreadpool(10); // 等价于:core=max=10, 无界 linkedblockingqueue // ❌ 坑:队列无界,任务堆积可能 oom // 2. 单线程 executorservice single = executors.newsinglethreadexecutor(); // 等价于:core=max=1, 无界 linkedblockingqueue // ❌ 坑:同上 // 3. 可缓存线程池 executorservice cached = executors.newcachedthreadpool(); // 等价于:core=0, max=integer.max_value, synchronousqueue, 60s 回收 // ❌ 坑:允许创建无限线程,可能 oom // 4. 定时任务 scheduledexecutorservice scheduled = executors.newscheduledthreadpool(5); // 等价于:core=5, max=integer.max_value, delayedworkqueue // ❌ 坑:max 无限制
不允许使用 executors 创建线程池,必须通过
threadpoolexecutor手动创建!
原因:executors 的便捷方法隐藏了风险参数(无界队列、无限线程数),生产环境极易 oom。
public class threadpoolmanager {
private static final int cpu_count = runtime.getruntime().availableprocessors();
private static final int core_pool_size = math.max(2, math.min(cpu_count - 1, 4));
private static final int max_pool_size = cpu_count * 2 + 1;
private static final long keep_alive = 30l;
private static final threadpoolexecutor executor = new threadpoolexecutor(
core_pool_size,
max_pool_size,
keep_alive,
timeunit.seconds,
new linkedblockingqueue<>(128), // ✅ 有界队列!
new threadfactory() {
private final atomicinteger count = new atomicinteger(1);
@override
public thread newthread(runnable r) {
return new thread(r, "app-pool-" + count.getandincrement());
}
},
new threadpoolexecutor.callerrunspolicy() // ✅ 自我保护
);
public static void execute(runnable task) {
executor.execute(task);
}
public static future<?> submit(runnable task) {
return executor.submit(task);
}
}// api 11+ 后 asynctask 内部线程池:
private static final int core_pool_size = 5;
private static final int maximum_pool_size = 128;
private static final int keep_alive = 1;
private static final blockingqueue<runnable> spoolworkqueue =
new linkedblockingqueue<runnable>(10); // 有界队列 10
asynctask在 android 3.0+ 默认是串行执行(serial_executor),可通过executeonexecutor()改为并行。
// dispatchers.default —— 对应 jvm 的 forkjoinpool.commonpool() // 线程数 = cpu 核心数(至少 2) // dispatchers.io —— 共享 default 的线程,但最大线程数为 64 // 适合阻塞 io 操作 // 自定义: val customdispatcher = executors.newfixedthreadpool(4).ascoroutinedispatcher()
| execute() | submit() | |
|---|---|---|
| 返回值 | void | future<t> |
| 异常处理 | 异常直接抛出,无法捕获 | 异常封装在 future 中,调用 get() 时抛出 |
| 参数 | 只能传 runnable | 可传 runnable 和 callable |
future<integer> future = executor.submit(() -> 42); integer result = future.get(); // 阻塞获取结果
executor.shutdown(); // 优雅关闭:不再接受新任务,等待已有任务完成
// executor.shutdownnow(); // 强制关闭:尝试中断正在执行的任务
try {
if (!executor.awaittermination(60, timeunit.seconds)) {
executor.shutdownnow(); // 超时后强制关闭
}
} catch (interruptedexception e) {
executor.shutdownnow();
}| 场景 | 公式/建议 |
|---|---|
| cpu 密集型(计算、加密) | cpu 核心数 + 1 |
| io 密集型(网络、文件) | cpu 核心数 * 2 或更大 |
| 混合型 | 拆分为两个线程池 |
android 中获取 cpu 核心数:
runtime.getruntime().availableprocessors()
workqueue 和 maximumpoolsize 的组合最危险。
如果用 无界队列(如 linkedblockingqueue 不指定容量),maximumpoolsize 将永远失效,因为队列永远不会满,线程数永远不会超过 corepoolsize。
这会导致任务无限堆积,最终 oom。
futuretask 实现了 runnablefuture(继承 runnable + future)。
内部维护一个状态机(new → completing → normal / exceptional)
get() 方法会阻塞,依赖 aqs(abstractqueuedsynchronizer)实现等待/唤醒
任务执行完成后通过 unsafe cas 修改状态,并唤醒等待线程
execute() 提交:异常抛出,线程终止,线程池会创建新线程替代
submit() 提交:异常被捕获封装到 future,线程不会终止
建议:在 runnable.run() 内部加 try-catch,或使用 thread.setuncaughtexceptionhandler()
// 常用指标 executor.getpoolsize(); // 当前线程数 executor.getactivecount(); // 活跃线程数 executor.getqueue().size(); // 队列积压数 executor.getcompletedtaskcount(); // 已完成任务数 executor.gettaskcount(); // 总任务数
可结合这些指标做动态告警(如队列积压超过阈值时扩容或报警)。
// 子线程池执行任务,结果通过 handler 抛回主线程
handler mainhandler = new handler(looper.getmainlooper());
executor.execute(() -> {
final bitmap bitmap = loadbitmap(url); // 耗时操作
mainhandler.post(() -> imageview.setimagebitmap(bitmap)); // ui 更新
});更现代的做法:使用 kotlin 协程
withcontext(dispatchers.io) { ... }自动切换。
corepoolsize = 0,所有线程都可回收
synchronousqueue 不存储任务,来任务立即创建线程执行
keepalivetime = 60s,线程空闲 60 秒后回收
适合大量短生命周期的任务,避免频繁创建/销毁线程的开销
// 并发请求多个接口,等待全部完成后统一处理
countdownlatch latch = new countdownlatch(3);
for (string url : urls) {
executor.execute(() -> {
try {
download(url);
} finally {
latch.countdown();
}
});
}
latch.await(); // 阻塞等待所有任务完成
mergeresults();线程池
├── 为什么用? → 复用、控制、管理
├── 核心类 threadpoolexecutor
│ ├── 7 大参数
│ ├── 任务提交流程(core → queue → max → reject)
│ └── 4 种拒绝策略
├── 队列类型(synchronousqueue / linkedblockingqueue / arrayblockingqueue)
├── executors 工厂(❌ 不推荐,隐藏 oom 风险)
├── android 实践
│ ├── 自定义有界线程池
│ ├── asynctask(已废弃,串行/并行)
│ └── kotlin 协程 dispatcher
└── 高频考点
├── submit vs execute
├── 优雅关闭
├── 线程数配置
├── futuretask 原理
└── 线程异常处理到此这篇关于java android线程池实践指南及高频问题的文章就介绍到这了,更多相关java线程池详解内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论