线程和线程池

115 阅读3分钟

一、线程本质与Android特殊约束

  1. 进程与线程的差异

    • 进程是资源分配单位,线程是CPU调度单位,共享进程内存空间但拥有独立栈
    • Android系统通过Zygote进程fork机制创建应用进程,主线程(UI线程)由AMS通过Binder驱动唤醒
  2. 主线程的特权与限制

    • 唯一持有ViewRootImpl的线程,所有UI操作必须在此执行
    • Looper.prepare() + Looper.loop()构建消息循环机制
    • 严格禁止耗时操作(>5秒触发ANR),需通过AsyncTask/HandlerThread/线程池隔离

二、线程池设计哲学与实现

  1. 线程池核心参数调优

    java
    	new ThreadPoolExecutor(
    
    	    corePoolSize,    // 核心线程数(建议CPU核心数+1)
    
    	    maxPoolSize,     // 最大线程数(建议根据任务类型动态调整)
    
    	    keepAliveTime,   // 空闲线程存活时间
    
    	    TimeUnit,
    
    	    workQueue,       // 阻塞队列选择(SynchronousQueue/LinkedBlockingQueue/ArrayBlockingQueue)
    
    	    threadFactory,   // 自定义线程命名(如:"image_loader_%d")
    
    	    handler          // 拒绝策略(CallerRunsPolicy兜底)
    
    	)
    
  2. Android线程池类型适配

    类型适用场景风险点
    newCachedThreadPool突发短时任务(如IO密集型)线程数无界导致OOM
    newFixedThreadPool持续稳定任务流队列积压导致响应延迟
    newScheduledThreadPool定时/周期任务(如心跳检测)需处理ScheduledFuture异常
    ProcessThreadPool系统级进程共享线程池(API 28+)需注意进程间协调

三、线程安全攻防策略

  1. 竞态条件典型案例

    • 共享变量未同步(如ConcurrentModificationException)

    • 资源释放时序问题(如Cursor未关闭导致泄漏)

    • 解决方案:

      java
      	// 原子类保证复合操作原子性
      
      	AtomicInteger counter = new AtomicInteger(0);
      
      	counter.getAndIncrement();
      
      	 
      
      	// 显式锁控制临界区
      
      	ReentrantLock lock = new ReentrantLock();
      
      	lock.lock();
      
      	try {
      
      	    // 修改共享资源
      
      	} finally {
      
      	    lock.unlock();
      
      	}
      
  2. 无锁编程实践

    • 使用Disruptor等环形缓冲区实现生产者-消费者模型
    • 消息队列采用CopyOnWriteArrayList实现读多写少场景优化

四、Android框架级线程管理

  1. HandlerThread深度解析

    • 自带Looper的线程,适用于需要与主线程交互的场景(如Bitmap解码)
    • 生命周期管理:需在onDestroy()调用quitSafely()避免泄漏
  2. IntentService遗产

    • 已废弃的后台任务方案,替代方案:

      • 短任务:WorkManager + CoroutineWorker
      • 长任务:Foreground Service + 自定义线程池
  3. 协程与线程池协同

    • Kotlin协程的Dispatcher.IO底层复用公共线程池
    • 通过withContext(Dispatchers.Default)实现CPU密集型任务隔离

五、性能优化实战经验

  1. 线程池监控方案

    • 埋点统计任务队列长度、线程活跃度
    • 通过LeakCanary检测线程泄漏
    • 使用StrictMode检测主线程违规操作
  2. IO密集型任务优化

    • 磁盘IO:使用线程池+LruCache二级缓存
    • 网络IO:配合OkHttp的Dispatcher线程池(默认64线程)
  3. CPU密集型任务调优

    • 图像处理:根据CPU核心数设置核心线程数(Runtime.getRuntime().availableProcessors())
    • 机器学习:使用RenderScript/NNAPI异步计算

六、前沿趋势思考

  1. Project Mainline模块化

    • 系统服务线程池逐步标准化(如StorageStatsService线程池)
    • 第三方应用需适配模块化线程隔离策略
  2. Jetpack Compose并发模型

    • 重组操作默认在UI线程执行,需通过rememberCoroutineScope启动后台任务
    • 使用LaunchedEffect实现声明式异步加载
  3. Kotlin Flow线程切换

    • flowOn操作符实现冷流线程切换
    • channelFlow构建生产者-消费者模型

总结:在Android开发中,线程管理已从简单的AsyncTask演进到需要综合考虑框架约束、硬件特性、生命周期管理的复杂工程问题。优秀的线程池策略应像手术刀般精准:既要避免线程饥饿导致的任务积压,又要防止过度创建线程引发的上下文切换开销,最终在响应速度与资源消耗间达成最佳平衡