线程池
问题
Android 中线程池的原理和使用方式有哪些?
答案
ThreadPoolExecutor 核心参数
val threadPool = ThreadPoolExecutor(
2, // corePoolSize:核心线程数
4, // maximumPoolSize:最大线程数
60L, // keepAliveTime:非核心线程闲置超时
TimeUnit.SECONDS, // 时间单位
LinkedBlockingQueue(100), // workQueue:任务队列
Executors.defaultThreadFactory(), // threadFactory
ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
)
任务执行流程
Executors 预定义线程池
| 类型 | 核心/最大线程 | 队列 | 用途 |
|---|---|---|---|
newFixedThreadPool(n) | n / n | 无界队列 | CPU 密集型 |
newCachedThreadPool() | 0 / MAX | SynchronousQueue | IO 密集型 |
newSingleThreadExecutor() | 1 / 1 | 无界队列 | 顺序执行 |
newScheduledThreadPool(n) | n / MAX | DelayQueue | 定时任务 |
不推荐直接使用 Executors
newFixedThreadPool 和 newSingleThreadExecutor 使用无界队列,可能导致 OOM。newCachedThreadPool 最大线程数为 Integer.MAX_VALUE,可能创建过多线程。推荐直接使用 ThreadPoolExecutor 明确指定参数。
Android 中的线程池使用
// 推荐:使用协程替代线程池
class ImageProcessor(
private val dispatcher: CoroutineDispatcher = Dispatchers.Default
) {
suspend fun processImages(images: List<Bitmap>): List<Bitmap> =
withContext(dispatcher) {
images.map { image ->
async { applyFilter(image) }
}.awaitAll()
}
}
// 仍需要线程池的场景:Java 代码、SDK 内部
object AppExecutors {
val diskIO = Executors.newSingleThreadExecutor()
val networkIO = Executors.newFixedThreadPool(3)
val mainThread = MainThreadExecutor()
private class MainThreadExecutor : Executor {
private val handler = Handler(Looper.getMainLooper())
override fun execute(command: Runnable) {
handler.post(command)
}
}
}
拒绝策略
| 策略 | 行为 |
|---|---|
AbortPolicy | 抛出 RejectedExecutionException(默认) |
CallerRunsPolicy | 在调用者线程执行(降速) |
DiscardPolicy | 静默丢弃 |
DiscardOldestPolicy | 丢弃队列头部最旧任务 |
常见面试问题
Q1: 核心线程数如何设置?
答案:
- CPU 密集型(计算、排序):核心线程数 = CPU 核心数 + 1
- IO 密集型(网络、文件):核心线程数 = CPU 核心数 × 2
Android 中可通过 Runtime.getRuntime().availableProcessors() 获取 CPU 核心数。实际建议使用协程的 Dispatchers.Default(CPU 核心数)和 Dispatchers.IO(最多 64 个线程)。
Q2: AsyncTask 为什么被废弃?
答案:
AsyncTask(API 30 废弃)的主要问题:
- 内存泄漏:内部类持有 Activity 引用
- 生命周期不感知:Activity 销毁后仍在执行,
onPostExecute更新已销毁的 UI - 串行/并行混乱:API 11 后默认串行执行,与直觉不符
- 异常处理困难:
doInBackground的异常难以传递
替代方案:Kotlin 协程 + viewModelScope / lifecycleScope。