一、进程(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. 通信策略

  • • 优先考虑LiveDataRxJava等响应式编程
  • • 复杂通信使用AIDL
  • • 简单数据共享用ContentProvider

七、常见问题与解决方案

Q1: ANR的原因和解决方法?

原因

  • • 主线程执行耗时操作(>5秒)
  • • 同步等待其他进程
  • • 广播接收器执行时间过长

解决

  • • 使用工作线程处理耗时任务
  • • 使用AsyncTaskLoaderViewModel
  • • 优化算法和数据结构

Q2: 如何选择线程池?

  • • CPU密集型任务:FixedThreadPool,线程数 = CPU核心数 + 1
  • • IO密集型任务:CachedThreadPool
  • • 定时任务:ScheduledThreadPool
  • • 单任务队列:SingleThreadExecutor

Q3: 多进程应用注意事项?

  1. 1. Application.onCreate()会调用多次
  2. 2. 静态变量不共享
  3. 3. 文件锁问题
  4. 4. 谨慎使用SharedPreferences(模式要正确)

八、总结表格

特性 进程 线程
内存空间 独立 共享
创建开销
通信成本 高(IPC) 低(直接访问)
崩溃影响 不影响其他进程 影响同一进程
Android管理 系统回收 开发者管理

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐