AndroidUtilCode之ThreadUtils:新手也能秒懂的线程池使用简单指南
【免费下载链接】AndroidUtilCode:fire: Android developers should collect the following utils(updating).项目地址: https://gitcode.com/gh_mirrors/an/AndroidUtilCode
AndroidUtilCode 是一款专为 Android 开发者打造的工具类库,其中的 ThreadUtils 是处理线程池和异步任务的明星工具类。它把复杂的线程池配置、任务调度、结果回调都封装成了"一行调用",新手不需要背诵ThreadPoolExecutor的参数含义,就能安全地执行后台任务、延时任务、周期任务和取消任务。
本文用通俗的比喻 + 少量示例,带你 3 分钟跑通 Android 线程池开发的全部常见场景 👇
为什么新手怕线程池?
自己用原生ThreadPoolExecutor创建线程池,你至少要回答这些问题:
- 核心线程数写几?最大线程数写几?
- 队列用无界还是有界?满了会怎样?
- 任务出异常了谁兜底?结果怎么回到主线程更新界面?
答错任何一个,轻则任务被拒绝、重则 App 崩溃卡死。
而 ThreadUtils 的思路是:你只说"我要干什么",池子怎么选、参数怎么配、异常怎么兜底,它都替你做了。
5种线程池怎么选:一张表看懂 🧭
ThreadUtils 内置了 5 种开箱即用的线程池,覆盖绝大多数场景:
| 线程池类型 | 获取方法 | 线程数策略 | 适用场景 |
|---|---|---|---|
| 固定线程池 | getFixedPool(4) | 你指定几个就是几个 | 业务明确的并发控制,如同时上传 4 张图 |
| 单线程池 | getSinglePool() | 永远只有 1 个线程 | 必须按顺序执行的任务,如按序读写数据库 |
| 缓存线程池 | getCachedPool() | 按需创建,上限 128 | 短生命周期、数量不定的任务 |
| IO 密集型线程池 | getIoPool() | 2×CPU核数+1 | 网络请求、文件读写等 IO 操作 |
| CPU 密集型线程池 | getCpuPool() | 核心 CPU核数+1,上限 2×CPU核数+1 | 图片压缩、加解密等纯计算任务 |
💡新手口诀:读写文件、发网络请求 → 选IO 池;算数据 → 选CPU 池;要排队执行 → 选单线程池;拿不准 → 选getFixedPool(2)先跑起来。
这些线程池都是全局单例复用的(见 ThreadUtils.java#L978-L996),同一个"类型 + 优先级"组合只创建一次,不会无限膨胀。
三步上手:写一个异步 Task
ThreadUtils 里所有任务都围绕Task抽象类展开(ThreadUtils.java#L1168-L1195),它只有 4 个必须实现的方法,职责非常清晰:
ThreadUtils.executeByIo(new ThreadUtils.SimpleTask<String>() { @Override public String doInBackground() throws Throwable { // 第 1 步:后台线程执行耗时操作(读写文件、请求网络) return FileIOUtils.readString4File(file); } @Override public void onSuccess(String result) { // 第 2 步:自动切回主线程,放心更新界面 tvContent.setText(result); } });新手只需要记住两件事:
doInBackground里只干耗时活,绝对不能碰控件;onSuccess自动回到主线程,可以直接操作 View——这是它比原生线程池最大的省心之处。
如果不想重写onFail/onCancel的日志打印,直接继承SimpleTask(ThreadUtils.java#L1154-L1166)即可,它会帮你把异常打印到 Log。
懒得分步写?也可以直接
ThreadUtils.executeByIo(runnable)把普通Runnable丢进 IO 池,一行完成。
延迟执行与周期任务:一行参数搞定 ⏰
ThreadUtils 把"延时"和"周期"做成了同族方法,命名规律非常好记:
- 立即执行:
executeByIo(task) - 延迟执行:
executeByIoWithDelay(task, 3, TimeUnit.SECONDS)—— 3 秒后再跑 - 固定速率周期:
executeByIoAtFixRate(task, 1, TimeUnit.SECONDS)—— 每 1 秒重复一次 - 先延迟再周期:
executeByIoAtFixRate(task, 5, 1, TimeUnit.SECONDS)—— 5 秒后开始,每 1 秒一次
五种池子(Fixed / Single / Cached / Io / CPU)各有一套对应方法,把方法名里的Io换成你选中的池子即可。官方测试用例 ThreadUtilsTest.java 覆盖了全部组合,照着抄就能跑。
任务取消与超时保护:防崩溃必备 🛡️
取消任务:任务对象随时可以调用cancel(),已排队的直接作废,正在执行的可被中断,回调会进入onCancel()(ThreadUtils.java#L865-L868):
ThreadUtils.cancel(myTask); // 取消单个任务 ThreadUtils.cancel(myPool); // 取消整个池子里的所有任务超时保护:通过setTimeout给任务上"保险丝",超过指定毫秒数未完成就触发超时回调并中断线程(ThreadUtils.java#L1311-L1315):
myTask.setTimeout(5000, () -> Log.w("TAG", "请求超时,该给用户提示了"));⚠️ 小贴士:周期任务(AtFixRate 系列)不支持超时保护,因为"每 1 秒执行一次"的任务天然没有"完成"概念。
ThreadUtils 在 AndroidUtilCode 中的位置
想深入源码?ThreadUtils 位于核心库utilcode模块,项目整体采用分层架构(lib 公共库层 → feature 功能层 → app 应用层):
常用入口文件清单:
- 核心实现:ThreadUtils.java
- 单元测试:ThreadUtilsTest.java
- 功能库使用示例:feature/utilcode/pkg/
- 库文档说明:lib/utilcode/README-CN.md
新手避坑清单 ✅
- 任务只能提交一次:同一个
Task对象重复提交会被拦截(日志提示 "Task can only be executed once"),需要重复执行请 new 新的 Task; - doInBackground 里别碰 UI:所有 View 操作统一放到
onSuccess,它已在主线程; - IO 密集别用 CPU 池:CPU 池线程数少,塞满 IO 任务会互相排队;
- 记得取消:页面销毁时调用
cancel(task),避免回调时页面已关闭导致崩溃; - 别忘加超时:网络类任务建议一律
setTimeout,防止无网环境无限等待。
总结
AndroidUtilCode 的 ThreadUtils 用"选池子 → 写 Task → 三选一(立即/延时/周期)"的极简模型,把 Android 线程池开发中 90% 的样板代码都消化掉了。配合取消、超时两大保护机制,新手也能写出生产级的异步代码 🚀 建议把 ThreadUtilsTest.java 作为随身手册,遇到问题先找对应的测试用例对照,基本都能秒懂。
【免费下载链接】AndroidUtilCode:fire: Android developers should collect the following utils(updating).项目地址: https://gitcode.com/gh_mirrors/an/AndroidUtilCode
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考