Android 中线程和进程详解
本文系统介绍了Android开发中的进程与线程机制。在进程方面,详细阐述了Android的五级进程优先级体系、多进程配置方法及其内存隔离特性。线程部分重点讲解了主线程与工作线程的区别,以及HandlerThread等Android特有线程机制。同时深入分析了进程间通信(IPC)的多种方式,包括AIDL实现细节。文章还提供了内存管理策略、线程同步方法和常见问题解决方案,为开发者优化应用性能提供了实用
·
一、进程(Process)
1. 基本概念
- • 独立的内存空间:每个进程有自己的内存地址空间
- • 系统资源分配的基本单位:CPU时间、内存等
- • Android中的进程:
- • 默认情况下,每个App运行在一个独立进程中
- • 可以通过AndroidManifest.xml配置多进程
2. Android进程级别(优先级从高到低)
| 进程类型 | 说明 | 回收优先级 |
| 前台进程(Foreground) | 用户正在交互的Activity,正在运行的Service | 最后回收 |
| 可见进程(Visible) | 不在前台但用户可见(如对话框后面的Activity) | 次之 |
| 服务进程(Service) | 通过startService()启动的服务 | 再次之 |
| 后台进程(Background) | 不可见且没有服务的Activity(onStop状态) | 优先回收 |
| 空进程(Empty) | 没有任何Activity组件,仅缓存进程 | 最先回收 |
3. 多进程配置
<!-- AndroidManifest.xml -->
<activity android:name=".MainActivity"
android:process=":remote"/> <!-- 私有进程 -->
<service android:name=".MyService"
android:process="com.example.myprocess"/> <!-- 全局进程 -->
4. 多进程特点
- • 内存隔离:每个进程有独立的内存空间
- • 通信复杂:需要使用IPC(进程间通信)
- • 数据不同步:静态变量、单例等不共享
- • 开销大:每个进程都有独立的虚拟机实例
二、线程(Thread)
1. 基本概念
- • 轻量级执行单元:同一进程内的多个线程共享内存空间
- • Android主线程(UI线程):
- • 负责处理UI更新和用户交互
- • 不能执行耗时操作(会ANR)
- • ANR时间限制:按键事件5秒,广播10秒
2. Android线程类型
(1)主线程(UI线程)
// 获取主线程
Looper.getMainLooper().getThread();
// 在主线程执行代码
runOnUiThread(new Runnable() {
@Override
public void run() {
// 更新UI
}
});
(2)工作线程
// 方式1:Thread
new Thread(new Runnable() {
@Override
public void run() {
// 后台任务
}
}).start();
// 方式2:AsyncTask(已废弃,了解即可)
(3)线程池
// 1. FixedThreadPool - 固定线程数
ExecutorService fixedPool = Executors.newFixedThreadPool(4);
// 2. CachedThreadPool - 弹性线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();
// 3. SingleThreadExecutor - 单线程
ExecutorService singleThread = Executors.newSingleThreadExecutor();
// 4. ScheduledThreadPool - 定时任务
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);
3. Android特有的线程机制
(1)HandlerThread
// 自带Looper的工作线程
HandlerThread handlerThread = new HandlerThread("MyHandlerThread");
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper()) {
@Override
public void handleMessage(@NonNull Message msg) {
// 在HandlerThread中处理消息
}
};
(2)IntentService(已被JobIntentService替代)
// 在后台线程处理Intent,处理完自动停止
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
// 在后台线程执行
}
}
三、进程间通信(IPC)
1. 主要IPC方式
| 方式 | 适用场景 | 特点 |
| Intent/Bundle | Activity/Service/Broadcast之间 | 简单,支持基本数据类型 |
| ContentProvider | 数据共享 | 结构化数据,支持跨进程查询 |
| Messenger | 基于消息的通信 | 串行处理,使用简单 |
| AIDL | 复杂接口调用 | 支持并发,功能强大 |
| Socket | 网络通信或本机通信 | 通用性强,开销较大 |
| 共享文件 | 简单数据交换 | 需要同步机制 |
2. AIDL示例
// IMyService.aidl
interface IMyService {
int add(int a, int b);
void registerCallback(IMyCallback callback);
}
// Service端
public class MyService extends Service {
private final IMyService.Stub mBinder = new IMyService.Stub() {
@Override
public int add(int a, int b) {
return a + b;
}
@Override
public void registerCallback(IMyCallback callback) {
// 注册回调
}
};
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
}
四、内存管理与优化
1. 进程内存限制
| 设备类型 | 普通App内存限制 | 大内存App限制 |
| 低端机 | 128MB | 256MB |
| 中端机 | 256MB | 512MB |
| 高端机 | 512MB | 1GB+ |
2. 内存泄漏常见场景
// 1. 非静态内部类持有外部类引用
public class MainActivity extends AppCompatActivity {
private Handler mHandler = new Handler() { // 潜在内存泄漏
@Override
public void handleMessage(Message msg) {
// ...
}
};
}
// 2. 单例模式持有Context
public class AppManager {
private static AppManager instance;
private Context context; // 可能持有Activity引用
public void init(Context context) {
this.context = context.getApplicationContext(); // 应该用Application Context
}
}
// 3. 资源未释放
public void loadImage() {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.large);
// 使用后未回收...
}
3. 内存优化建议
// 1. 使用弱引用
WeakReference<Activity> activityRef = new WeakReference<>(activity);
// 2. 及时释放资源
@Override
protected void onDestroy() {
super.onDestroy();
if (mHandler != null) {
mHandler.removeCallbacksAndMessages(null);
}
// 释放其他资源
}
// 3. 使用LeakCanary检测
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
}
五、线程同步与并发
1. 同步机制
// 1. synchronized
public synchronized void syncMethod() {
// 同步方法
}
// 2. ReentrantLock
private final ReentrantLock lock = new ReentrantLock();
public void threadSafeMethod() {
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock();
}
}
// 3. 原子类
private AtomicInteger counter = new AtomicInteger(0);
counter.incrementAndGet();
2. Android特有并发类
// 1. AsyncTaskLoader - 替代AsyncTask
public class MyLoader extends AsyncTaskLoader<List<String>> {
@Override
public List<String> loadInBackground() {
// 在后台线程执行
return fetchData();
}
}
// 2. ViewModel + LiveData
public class MyViewModel extends ViewModel {
private MutableLiveData<List<String>> data = new MutableLiveData<>();
public void loadData() {
// ViewModel自动管理生命周期
}
}
六、最佳实践
1. 进程策略
- • 尽量使用单进程,除非有特殊需求
- • 将Service、ContentProvider等放在不同进程要考虑通信成本
- • 使用
android:largeHeap="true"要谨慎
2. 线程策略
- • UI操作必须在主线程
- • 耗时操作使用线程池
- • 避免在循环中创建线程
- • 使用
StrictMode检测主线程耗时操作
// 检测主线程耗时操作
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.build());
}
3. 通信策略
- • 优先考虑
LiveData、RxJava等响应式编程 - • 复杂通信使用AIDL
- • 简单数据共享用
ContentProvider
七、常见问题与解决方案
Q1: ANR的原因和解决方法?
原因:
- • 主线程执行耗时操作(>5秒)
- • 同步等待其他进程
- • 广播接收器执行时间过长
解决:
- • 使用工作线程处理耗时任务
- • 使用
AsyncTaskLoader或ViewModel - • 优化算法和数据结构
Q2: 如何选择线程池?
- • CPU密集型任务:FixedThreadPool,线程数 = CPU核心数 + 1
- • IO密集型任务:CachedThreadPool
- • 定时任务:ScheduledThreadPool
- • 单任务队列:SingleThreadExecutor
Q3: 多进程应用注意事项?
- 1. Application.onCreate()会调用多次
- 2. 静态变量不共享
- 3. 文件锁问题
- 4. 谨慎使用SharedPreferences(模式要正确)
八、总结表格
| 特性 | 进程 | 线程 |
| 内存空间 | 独立 | 共享 |
| 创建开销 | 大 | 小 |
| 通信成本 | 高(IPC) | 低(直接访问) |
| 崩溃影响 | 不影响其他进程 | 影响同一进程 |
| Android管理 | 系统回收 | 开发者管理 |
更多推荐


所有评论(0)