1. Android多线程基础与核心机制
在移动应用开发中,多线程技术是解决界面卡顿、提升响应速度的关键手段。Android系统基于Linux内核实现线程管理,但相比标准Java线程又增加了特有的交互机制。我们先从最基础的线程创建方式开始剖析。
1.1 继承Thread类实现
这是Java中最原始的线程创建方式,在Android中同样适用:
class MyThread extends Thread { @Override public void run() { // 耗时操作代码 Log.d("Thread", "ID:" + Thread.currentThread().getId()); } } // 启动线程 new MyThread().start();注意:直接继承Thread的方式在Android中并不推荐,因为Java是单继承语言,这会限制类的扩展性。但在需要完全控制线程生命周期时仍可考虑使用。
1.2 实现Runnable接口
更灵活的方案是实现Runnable接口:
class MyRunnable implements Runnable { @Override public void run() { // 后台任务逻辑 } } // 使用方式 new Thread(new MyRunnable()).start();这种方式的优势在于:
- 避免单继承限制
- 便于线程池管理
- 任务与执行器解耦
1.3 Handler消息机制
Android特有的线程间通信方案:
Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { // 主线程处理UI更新 } }; new Thread(() -> { // 子线程执行任务 Message msg = handler.obtainMessage(); msg.sendToTarget(); }).start();关键组件说明:
- Looper:消息循环泵,维护消息队列
- MessageQueue:消息存储结构
- Handler:消息发送和处理枢纽
2. Android多线程进阶方案
2.1 AsyncTask的工作原理
虽然官方已不推荐使用,但理解其设计思想仍有价值:
class DownloadTask extends AsyncTask<URL, Integer, Long> { protected Long doInBackground(URL... urls) { // 后台执行 publishProgress(progress); // 更新进度 return result; } protected void onProgressUpdate(Integer... progress) { // UI线程更新进度条 } protected void onPostExecute(Long result) { // 执行完成回调 } }内部实现要点:
- 默认使用串行线程池(SerialExecutor)
- 通过InternalHandler实现线程切换
- 状态机管理(PENDING→RUNNING→FINISHED)
实际开发中建议用更现代的方案替代AsyncTask,如Kotlin协程或RxJava
2.2 HandlerThread应用场景
适合需要长期运行的后台任务:
HandlerThread handlerThread = new HandlerThread("MyHandlerThread"); handlerThread.start(); Handler handler = new Handler(handlerThread.getLooper()) { @Override public void handleMessage(Message msg) { // 在子线程处理消息 } };典型使用场景:
- 文件系统监控
- 低优先级后台任务
- 需要顺序执行的任务队列
2.3 IntentService设计解析
虽然已被JobIntentService取代,但其设计值得学习:
class MyIntentService extends IntentService { public MyIntentService() { super("MyIntentService"); } @Override protected void onHandleIntent(Intent intent) { // 串行处理Intent请求 } }核心特点:
- 自动创建Worker线程
- 任务执行完成后自动停止服务
- 所有请求按顺序执行
3. 现代Android多线程方案
3.1 Kotlin协程实践
协程已成为Android官方推荐方案:
// 启动协程 lifecycleScope.launch { val data = withContext(Dispatchers.IO) { // 网络请求或数据库操作 } // 自动切换回主线程更新UI updateUI(data) }关键概念:
- CoroutineScope:协程作用域(ViewModelScope、LifecycleScope等)
- Dispatcher:调度器(IO、Default、Main)
- Suspend函数:可挂起函数标记
3.2 WorkManager定时任务
适合需要保证执行的后台任务:
val uploadWork = OneTimeWorkRequestBuilder<UploadWorker>() .setConstraints( Constraints.Builder() .setRequiredNetworkType(NetworkType.CONNECTED) .build() ) .build() WorkManager.getInstance(context).enqueue(uploadWork)优势特性:
- 兼容不同API级别
- 支持任务链(Chain)
- 内置电池优化处理
3.3 RxJava线程控制
虽然学习曲线陡峭,但功能强大:
Observable.fromCallable(() -> { // 子线程执行 return fetchData(); }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { // 主线程处理结果 });线程调度器类型:
- Schedulers.io():I/O密集型任务
- Schedulers.computation():CPU密集型计算
- Schedulers.newThread():每次创建新线程
4. 多线程编程的陷阱与优化
4.1 内存泄漏防范
典型场景及解决方案:
// 错误示例:匿名内部类持有Activity引用 new Thread(() -> { // 长时间运行任务 activity.updateUI(); // 可能导致泄漏 }).start(); // 正确做法:使用弱引用 static class MyRunnable implements Runnable { private final WeakReference<Activity> weakActivity; MyRunnable(Activity activity) { this.weakActivity = new WeakReference<>(activity); } @Override public void run() { Activity activity = weakActivity.get(); if (activity != null && !activity.isFinishing()) { activity.runOnUiThread(() -> { // 安全更新UI }); } } }4.2 线程安全实践
常见线程安全问题示例:
// 非线程安全的单例 class UnsafeSingleton { private static UnsafeSingleton instance; public static UnsafeSingleton getInstance() { if (instance == null) { instance = new UnsafeSingleton(); // 多线程可能重复创建 } return instance; } } // 改进方案1:双重检查锁定 class SafeSingleton { private static volatile SafeSingleton instance; public static SafeSingleton getInstance() { if (instance == null) { synchronized (SafeSingleton.class) { if (instance == null) { instance = new SafeSingleton(); } } } return instance; } }4.3 性能优化策略
线程池的最佳实践:
// 自定义线程池 ExecutorService executor = new ThreadPoolExecutor( 4, // 核心线程数 10, // 最大线程数 60L, TimeUnit.SECONDS, // 空闲线程存活时间 new LinkedBlockingQueue<>(100), // 任务队列 new ThreadFactory() { private final AtomicInteger count = new AtomicInteger(1); public Thread newThread(Runnable r) { return new Thread(r, "MyThread #" + count.getAndIncrement()); } }, new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略 );关键参数说明:
- 核心线程数:常驻线程数量
- 最大线程数:突发负载时的扩容上限
- 存活时间:非核心线程的空闲回收阈值
- 工作队列:缓冲待处理任务
- 拒绝策略:任务过载时的处理方式
5. 复杂场景下的线程管理
5.1 多线程下载实现
分块下载的典型实现:
// 创建下载任务列表 List<DownloadTask> tasks = new ArrayList<>(); long fileSize = getRemoteFileSize(); long blockSize = fileSize / THREAD_COUNT; for (int i = 0; i < THREAD_COUNT; i++) { long start = i * blockSize; long end = (i == THREAD_COUNT - 1) ? fileSize - 1 : start + blockSize - 1; tasks.add(new DownloadTask(url, start, end, outputFile)); } // 使用CountDownLatch同步 CountDownLatch latch = new CountDownLatch(THREAD_COUNT); ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT); for (DownloadTask task : tasks) { executor.execute(() -> { try { task.execute(); } finally { latch.countDown(); } }); } // 等待所有任务完成 latch.await(); executor.shutdown();5.2 数据库多线程访问
Room数据库的线程安全实践:
@Dao interface UserDao { @Insert suspend fun insert(user: User) @Query("SELECT * FROM user") fun getAll(): LiveData<List<User>> } // 在ViewModel中使用 class UserViewModel : ViewModel() { private val dao = database.userDao() val users: LiveData<List<User>> = dao.getAll() fun addUser(user: User) { viewModelScope.launch { withContext(Dispatchers.IO) { dao.insert(user) } } } }Room的线程安全特性:
- 自动检测主线程数据库操作
- LiveData自动异步查询
- 协程支持简化异步操作
5.3 网络请求并发控制
使用OkHttp的调度器控制:
OkHttpClient client = new OkHttpClient.Builder() .dispatcher(new Dispatcher(new ThreadPoolExecutor( 5, // 最大并发请求数 10, 60, TimeUnit.SECONDS, new SynchronousQueue(), new ThreadPoolExecutor.DiscardPolicy() ))) .build();高级控制技巧:
- 域名级别并发控制
- 请求优先级设置
- 请求取消机制
- 自动重试策略