1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| 在安卓中,安全使用线程池是保证应用性能、避免 ANR 和内存泄漏的重要手段。
1️⃣ 为什么要用线程池
避免频繁创建和销毁线程,线程创建成本高。
限制线程数量,避免系统过载。
复用线程,提高性能。
安卓开发中常用线程池有两类:
Executors 提供的便捷方法:如 newFixedThreadPool、newCachedThreadPool、newSingleThreadExecutor。
自定义 ThreadPoolExecutor:灵活配置核心线程数、最大线程数、队列大小、拒绝策略。
2️⃣ 常用线程池写法 ① 固定线程池(FixedThreadPool) ExecutorService fixedPool = Executors.newFixedThreadPool(4); // 固定4个线程
fixedPool.execute(() -> { // 耗时任务 doHeavyTask(); });
适合:任务数量大但线程数可控的情况。
② 缓存线程池(CachedThreadPool) ExecutorService cachedPool = Executors.newCachedThreadPool();
cachedPool.execute(() -> { doHeavyTask(); });
特点:有新任务就创建线程,空闲线程 60s 后销毁。
适合:执行短时异步任务,数量不确定。
风险:任务过多会无限开线程 → OOM。
③ 单线程池(SingleThreadExecutor) ExecutorService singlePool = Executors.newSingleThreadExecutor(); singlePool.execute(() -> { // 顺序执行任务 });
特点:任务按顺序执行,保证顺序性。
适合:任务必须按顺序执行的场景,比如写文件、写数据库。
④ 自定义线程池(ThreadPoolExecutor) ThreadPoolExecutor executor = new ThreadPoolExecutor( 4, // 核心线程数 8, // 最大线程数 60, // 空闲线程存活时间 TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), // 队列大小 Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 );
优点:灵活可控。
拒绝策略:
AbortPolicy → 抛异常
CallerRunsPolicy → 在调用者线程执行
DiscardPolicy → 丢弃任务
DiscardOldestPolicy → 丢弃最老任务
3️⃣ 安全使用线程池的注意点
避免 UI 更新在子线程
executor.execute(() -> { // 耗时任务 String result = doHeavyTask();
// UI更新 runOnUiThread(() -> textView.setText(result)); });
避免线程泄漏
Activity/Fragment 销毁时要关闭线程池:
@Override protected void onDestroy() { super.onDestroy(); executor.shutdownNow(); // 停止所有任务 }
使用有限队列和核心线程数
防止任务无限堆积,导致 OOM。
结合生命周期感知组件
可以用 ViewModel + LiveData / RxJava / Coroutine 来管理线程和 UI 更新。
4️⃣ 推荐组合方式
IO密集型任务(网络请求、文件读写):
ExecutorService ioPool = Executors.newCachedThreadPool();
CPU密集型任务(计算):
int cpuCount = Runtime.getRuntime().availableProcessors(); ExecutorService cpuPool = Executors.newFixedThreadPool(cpuCount);
|