Android 进程与线程模型:Zygote�主线程�Binder 线程池解�

3638 2026-09-25 01:34:16

引言:并�执行的基石与挑战

在 Android 系统中,所有应用程åº�代ç �都è¿�行在特定的进程和线程上下文中。进程æ��供资æº�隔离和独立è¿�行的环境,线程则是 CPU 调度的基本å�•ä½�,负责执行具体的代ç �指令。ç�†è§£ Android 如何创建ã€�管ç�†ã€�调度进程(包括其生命周期ã€�优先级和终止机制),以å�Šå¦‚何在进程内有效地组织和管ç�†çº¿ç¨‹ï¼ˆä¸»çº¿ç¨‹ã€�Binder 线程ã€�å�Žå�°çº¿ç¨‹ï¼‰ï¼ŒåŒ…括它们之间的å�Œæ­¥ä¸Žé€šä¿¡ï¼Œå¯¹äºŽæž„建稳定ã€�æµ�ç•…ã€�å“�应迅速的应用至关é‡�è¦�。

对于 Android 专家而言,仅仅掌æ�¡ Thread 的基本用法或知é�“ UI æ“�作è¦�在主线程执行是远远ä¸�够的。必须深入ç�†è§£ Linux 进程/线程的底层基础ã€�Android 独特的进程生命周期与 OOM 优先级调整机制(oom_adj)ã€�主线程的至高地ä½�与性能瓶颈ã€�Binder çº¿ç¨‹æ± çš„å·¥ä½œåŽŸç�†ã€�高级å�Žå�°ä»»åС处ç�†ç­–ç•¥ã€�Handler/Looper 消æ�¯æœºåˆ¶çš„内部细节ã€�å¤�æ�‚场景下的线程å�Œæ­¥æŠ€æœ¯ï¼Œä»¥å�Š ANR(Application Not Responding)的系统性分æž�方法。这ç§�深层次的ç�†è§£æ˜¯è§£å†³å¹¶å�‘问题ã€�优化å“�应速度ã€�分æž�系统级异常行为的基础。

本文将深入探讨 Android 的进程与线程模型,涵盖以下内容:

底层基础:Linux 进程与线程概念回顾

Android 进程:Zygote 孵化�生命周期�优先级与 OOM Killer(oom_adj)

主线程剖�:UI 线程的关键�责与性能约�

Binder 线程:处ç�† IPC çš„æ ¸å¿ƒçº¿ç¨‹æ±

��线程策略:ExecutorService�Coroutines 等现代并�方案

Handler 机制详解:Looper�MessageQueue�ThreadLocal 的内部�作

高级�步:��原�类�并�工具(CountDownLatch�Semaphore 等)的原�与应用

ANR 深度分æž�ï¼šç³»ç»Ÿæ€§åœ°è¯Šæ–­å’Œè§£å†³åº”ç”¨æ— å“�应问题

一�底层基础:Linux 进程与线程模型

Android 构建于 Linux å†…æ ¸ä¹‹ä¸Šï¼Œå…¶è¿›ç¨‹å’Œçº¿ç¨‹æ¨¡åž‹ç›´æŽ¥ç»§æ‰¿è‡ª Linux。

进程(Process)

是程�执行时的一个实例

拥有独立的虚拟地å�€ç©ºé—´ã€�内存ã€�æ•°æ�®æ ˆä»¥å�Šæ–‡ä»¶æ��述符等系统资æº�

进程间相互隔离,通信需�通过 IPC 机制(如 Binder�Socket�Pipe)

Linux 通过 fork() 系统调用创建å­�进程(å¤�制父进程地å�€ç©ºé—´ï¼‰ï¼Œé€šå¸¸å­�进程会接ç�€è°ƒç”¨ exec() 系列系统调用æ�¥åŠ è½½å¹¶æ‰§è¡Œæ–°çš„ç¨‹åº�镜åƒ�

线程(Thread)

是进程内的一个执行�元,是 CPU 调度的基本��

å�Œä¸€è¿›ç¨‹å†…的线程共享该进程的虚拟地å�€ç©ºé—´ã€�内存资æº�(代ç �段ã€�æ•°æ�®æ®µã€�å †å†…å­˜ï¼‰å’Œæ–‡ä»¶æ��述符

æ¯�个线程拥有自己独立的程åº�计数器ã€�寄存器ã€�çº¿ç¨‹æ ˆï¼ˆç”¨äºŽå­˜å‚¨å±€éƒ¨å�˜é‡�和函数调用信æ�¯ï¼‰

线程间的切�(上下文切�)通常比进程切�开销�得多

Linux å†…æ ¸ä¸­ï¼Œçº¿ç¨‹ï¼ˆLightweight Process, LWP)是通过 clone() 系统调用以特定å�‚数创建的,它æ��供了比 fork() æ›´ç�µæ´»çš„资æº�共享选项。用户空间通常使用 POSIX 线程库(pthread)æ�¥åˆ›å»ºå’Œç®¡ç�†çº¿ç¨‹

Android 应用上下文

æ¯�个 Android 应用默认è¿�行在一个独立的 Linux 进程中,拥有唯一的 UID(用户 ID)和 GID(组 ID),实现了应用间的安全沙箱隔离。应用内的所有代ç �ï¼Œæ— è®ºæ˜¯ Java/Kotlin 还是 Native,都执行在属于该进程的æŸ�个线程上。

二�Android 进程模型:被管�的生命周期与优先级

Android 系统对应用进程的管ç�†è¿œæ¯”æ ‡å‡† Linux æ›´ä¸ºä¸¥æ ¼å’Œä¸»åŠ¨ï¼Œæ ¸å¿ƒç›®æ ‡æ˜¯ä¿�障系统æµ�畅性和用户体验。

Zygote 孵化进程

如�所述,所有应用进程(以� SystemServer)都由 Zygote 进程通过 fork() 创建。这使得新进程能够快速�动并共享内存(Copy-on-Write)。

进程生命周期与状�(� AMS 管�)

Android ç³»ç»Ÿæ ¹æ�®åº”用组件的状æ€�å’Œç”¨æˆ·äº¤äº’æƒ…å†µï¼Œå°†è¿›ç¨‹å¤§è‡´åˆ†ä¸ºå‡ ä¸ªä¼˜å…ˆçº§ç±»åˆ«ï¼Œè¿™ç›´æŽ¥å†³å®šäº†è¿›ç¨‹åœ¨å†…å­˜ä¸�足时被æ�€æ­»çš„å�¯èƒ½æ€§ã€‚

��进程(Foreground Process)

用户当�正在交互的应用(顶部的 Activity 处于 Resumed 状�)

托管�与用户交互的 Activity 绑定的 Service

托管�调用了 startForeground() 的 Service(显示�续通知)

托管�正在执行生命周期回调(onCreate�onStart�onDestroy)的 Service

托管�正在执行 onReceive() 的 BroadcastReceiver

优先级最高,系统�有在万�得已(内存�度匮�)时�会�死它。

��进程(Visible Process)

拥有用户��但�在��的 Activity(例如,Activity 被一个�全�的 Dialog 或 Activity 部分�挡,处于 Paused 状�)

托管�与�� Activity 绑定的 Service

优先级很高,除�为了����进程的�行,�则�会被�死。

�务进程(Service Process)

托管�通过 startService() �动且�在�行的 Service,并且该 Service �属于��或��进程类别

优先级高于��进程,但低于��进程。�行时间过长且���的�务进程也�能被回收。

缓存进程(Cached Process)

�包�任何�����或�务组件。通常包�用户已退出但�在内存中(Activity 处于 Stopped 状�)的应用,以便下次快速�动

优先级最低,是系统内存ä¸�足时最先被æ�€æ­»çš„对象。 ç¼“å­˜è¿›ç¨‹å†…éƒ¨ä¹Ÿæ ¹æ�® LRU(最近最少使用)等策略进一步细分优先级(如空进程ã€�å‰�一个应用进程ã€�主å±�幕进程等)。

(图示:Android 进程优先级)

Most Important (Least likely to be killed)

^

|

+-------------------------+

| Foreground Process | (Activity Resumed, Foreground Service) <- oom_adj ~ 0

+-------------------------+

|

+-------------------------+

| Visible Process | (Activity Paused but Visible) <- oom_adj ~ 100-200

+-------------------------+

|

+-------------------------+

| Service Process | (Started Service running) <- oom_adj ~ 500+

+-------------------------+

|

+-------------------------+

| Cached Process (LRU) | (Activity Stopped/Destroyed, Empty) <- oom_adj ~ 900+

+-------------------------+

|

V

Least Important (Most likely to be killed)

OOM Killer 与 oom_adj 分数

LMK(Low Memory Killer):Android å†…æ ¸ä¸­çš„ä¸€ä¸ªé©±åŠ¨æˆ–æœºåˆ¶ï¼Œè´Ÿè´£åœ¨ç³»ç»Ÿå†…å­˜ä½ŽäºŽç‰¹å®šé˜ˆå€¼æ—¶ï¼Œæ ¹æ�®è¿›ç¨‹çš„优先级æ�€æ­»è¿›ç¨‹ä»¥å›žæ”¶å†…存。

oom_adj(Out-of-Memory Adjustment)分数:这是 AMS(ActivityManagerService)计算并设置给æ¯�ä¸ªè¿›ç¨‹çš„ä¸€ä¸ªå…³é”®å†…æ ¸å�‚数(ä½�于 /proc//oom_score_adj)。它的值范围大致在 -1000(永ä¸�æ�€æ­»ï¼Œå¦‚系统进程)到 +1000(最容易æ�€æ­»ï¼Œå¦‚空缓存进程)。oom_adj 值越低,进程越é‡�è¦�,越ä¸�容易被 LMK æ�€æ­»ã€‚

动æ€�调整:AMS ä¼šæ ¹æ�®è¿›ç¨‹ä¸­è¿�行的组件状æ€�(Activity 是å�¦å�¯è§�ã€�Service 是å�¦å‰�å�°ã€�是å�¦æœ‰ç»‘定连接等)动æ€�地调整进程的 oom_adj 分数。例如,当 Activity 进入å�Žå�°ï¼Œå…¶æ‰€åœ¨è¿›ç¨‹çš„ oom_adj 会å�‡é«˜ï¼›å½“ Service 调用 startForeground(),其进程的 oom_adj 会é™�低。

�解 oom_adj 的计算和影�,对于以下场景至关��:

��任务设计:选择�适的��机制(如 Foreground Service�WorkManager)以��任务在低内存情况下尽�能存活

分�进程被�:当应用进程�外消失时,检查其被��的 oom_adj 分数和系统内存状�是关键线索

优化内存å� 用:å‡�少应用的内存å� 用å�¯ä»¥é™�低整体系统内存压力,间接æ��高自身进程的存活率

多进程应用

场景:通过在 AndroidManifest.xml 中使用 android:process 属性,�以将应用的��组件(Activity�Service�Receiver�Provider)�行在��的进程中。

优点:隔离性(一个进程崩溃�影�其他进程)��能绕过�进程内存上�(但整体内存消耗通常更高)�安全性(如将�感�作放在独立进程)。

挑战:

IPC 开销:进程间通信必须通过 Binder(AIDL)�Messenger�ContentProvider 或 Socket 等机制,带��外的性能开销和实现��度

å†…å­˜å¢žåŠ ï¼šæ¯�个进程都有独立的虚拟机实例和è¿�行时开销,总体内存å� 用高于å�•进程

管���:需�仔细设计进程间�赖�生命周期�步�数�共享等问题

多进程是一�架构选择,需�仔细�衡其带�的好处和�本,通常�在有明确需求(如稳定性隔离�特殊内存需求)时�采用。

三�Android 主线程(UI 线程):心�与瓶颈

应用进程�动时创建的第一个线程,通常被称为主线程或 UI 线程。

æ ¸å¿ƒè�Œè´£

UI 交互处�:分�和处�用户输入事件(触摸�按键)

UI 绘制:执行 Choreographer 回调,进行 Measure�Layout�Draw

组件生命周期:执行 Activity�Service�BroadcastReceiver 等组件的生命周期回调方法(onCreate�onStart�onResume�onReceive 等)

主 Looper 任务:执行通过与主线程 Looper 关�的 Handler post 过�的 Runnable 或 Message

黄金法则:永�阻塞主线程

åŽŸå› ï¼šä¸»çº¿ç¨‹è´Ÿè´£å¤„ç�†æ‰€æœ‰ä¸Žç”¨æˆ·äº¤äº’和界é�¢æ›´æ–°çš„任务。任何耗时æ“�作(网络请求ã€�æ•°æ�®åº“读写ã€�å¤�æ�‚计算ã€�文件 IO,甚至æŸ�些有争议的é”�等待)如果å�‘生在主线程,都会阻止其处ç�†æ–°çš„ UI 事件或绘制请求。

�果:

轻微:掉帧(Jank)�动画�顿�界�失去�应

严�:触� ANR(Application Not Responding)对�框,用户�能选择强制关闭应用

四�Binder 线程:跨进程通信的执行者

如 Binder ç« èŠ‚æ‰€è¿°ï¼Œå½“å…¶ä»–è¿›ç¨‹ï¼ˆåŒ…æ‹¬ç³»ç»Ÿæœ�务)通过 Binder 调用当å‰�进程æ��供的æœ�务时,请求是在专门的 Binder 线程上执行的。

Binder çº¿ç¨‹æ± ï¼šæ¯�个æ��ä¾› Binder æœ�åŠ¡çš„è¿›ç¨‹ç»´æŠ¤ä¸€ä¸ªçº¿ç¨‹æ± ï¼ˆç”± libbinder å’Œå†…æ ¸é©±åŠ¨ç®¡ç�†ï¼‰ï¼Œç”¨äºŽå¹¶å�‘处ç�†ä¼ 入的 IPC 调用。默认上é™�通常是 15 个线程(主线程除外)。

执行上下文:AIDL 接å�£æ–¹æ³•的实现代ç �(或 Binder.onTransact)è¿�行在 Binder 线程上。

æ ¸å¿ƒè§„åˆ™

ç¦�止耗时æ“�作:å�Œæ ·åœ°ï¼Œä¸�能在 Binder 线程中执行å�¯èƒ½é˜»å¡žçš„æ“�作,å�¦åˆ™ä¼šè€—å°½çº¿ç¨‹æ± èµ„æº�,导致å�Žç»­çš„ IPC 请求(包括æ�¥è‡ªç³»ç»Ÿçš„é‡�è¦�è°ƒç”¨ï¼‰æ— æ³•è¢«å�Šæ—¶å¤„ç�†ï¼Œå¼•å�‘æ­»é”�或 ANR。必须将耗时任务异步化

�止直接 UI 更新:Binder 线程�能直接�作 UI 组件。需�通过 Handler 将 UI 更新任务切�回主线程执行

线程安全:如果 Binder 方法访问了�能被主线程或其他��线程并�访问的共享数�,必须采�正确的�步措施

五���线程策略:将耗时任务请出主线程

为了�守「�阻塞主线程/Binder 线程�的规则,必须将耗时任务放到��线程执行。

基本 Thread + Runnable

最基础的方�,�活但管���。需�手动处�线程生命周期�中断�错误�与主线程通信等,容易出错。

ExecutorService / ThreadPoolExecutor

推è��æ–¹å¼�:æ��ä¾›çº¿ç¨‹æ± ç®¡ç�†ï¼Œå¤�用线程,é�¿å…�频ç¹�创建销æ¯�线程的开销。

ç�µæ´»æ€§ï¼šå�¯ä»¥é…�ç½®æ ¸å¿ƒçº¿ç¨‹æ•°ã€�最大线程数ã€�线程存活时间ã€�任务队列类型(有界/æ— ç•Œï¼‰ã€�æ‹’ç»�策略。

使用:通过 Executors å·¥åŽ‚ç±»åˆ›å»ºå¸¸ç”¨ç±»åž‹çº¿ç¨‹æ± ï¼ˆnewFixedThreadPoolã€�newCachedThreadPoolã€�newSingleThreadExecutorï¼‰ï¼Œæˆ–ç›´æŽ¥æž„é€ ThreadPoolExecutor 进行精细控制。使用 submit() 或 execute() æ��交 Runnable 或 Callable 任务。

æ ¹æ�®ä»»åŠ¡ç±»åž‹ï¼ˆCPU 密集型 vs IO 密集型)å�ˆç�†é…�ç½®çº¿ç¨‹æ± å¤§å°�(CPU 密集型通常接近 CPU æ ¸å¿ƒæ•°ï¼ŒIO 密集型å�¯ä»¥æ›´å¤§ï¼‰ï¼›é€‰æ‹©å�ˆé€‚的任务队列和拒ç»�策略;注æ„�çº¿ç¨‹æ± çš„ç”Ÿå‘½å‘¨æœŸç®¡ç�†ï¼ˆé€‚æ—¶ shutdown())。

AsyncTask(已弃用)

已弃用,��推�使用。

IntentService(已弃用)/ JobIntentService

已弃用,建议使用 WorkManager 等替代方案。

Kotlin Coroutines(�程)——现代首选

轻�级:�程是�行在线程之上的��挂起和��的计算�元,比线程更轻�。�以创建大��程而�会耗尽系统资�

简化异步:使用 suspend 关键字使得异步代ç �写起æ�¥åƒ�å�Œæ­¥ä»£ç �ä¸€æ ·ç›´è§‚

结构化并�:�供了 CoroutineScope(如 viewModelScope�lifecycleScope)�管��程的生命周期,与组件生命周期绑定,自动�消,�大�少泄�风险

调度器(Dispatchers):方便地在��线程(Dispatchers.Main�Dispatchers.IO�Dispatchers.Default)之间切��程执行上下文

生�:与 Jetpack 库(LiveData�ViewModel�Room 等)深度集�。是目� Kotlin 开� Android 应用进行并�编程的首选方案

RxJava / RxAndroid

�应�编程:基于观察者模�,使用强大的�作符链�组��转��过滤异步事件�

优点:处���异步逻辑�多数���并�背压等场景�常强大

ç¼ºç‚¹ï¼šå­¦ä¹ æ›²çº¿è¾ƒé™¡å³­ï¼Œæ¦‚å¿µè¾ƒå¤šï¼ˆObservableã€�Operatorã€�Scheduler 等),代ç �å�¯èƒ½ä¸�易ç�†è§£

六�Handler�Looper�MessageQueue 详解:Android 线程通信的基石

这是 Android 框架内部广泛使用的线程通信和任务调度机制,尤其用于在ä¸�å�Œçº¿ç¨‹é—´å®‰å…¨åœ°ä¼ 递消æ�¯å’Œæ‰§è¡Œä»»åŠ¡ï¼ˆç‰¹åˆ«æ˜¯åˆ‡æ�¢å›žä¸»çº¿ç¨‹ï¼‰ã€‚

æ ¸å¿ƒç»„ä»¶

Message:æ�ºå¸¦å°‘é‡�æ•°æ�®ï¼ˆwhatã€�arg1ã€�arg2ã€�obj——é�¿å…�用 obj ä¼ é€’å¤§å¯¹è±¡ï¼Œè€ƒè™‘ setData(Bundle))或一个 Runnable 任务。包å�«ä¸€ä¸ª target 字段指å�‘处ç�†å®ƒçš„ Handler。

MessageQueue:æ¯�个拥有 Looper 的线程都有一个 MessageQueue。它按执行时间顺åº�存储待处ç�†çš„ Message。当队列为空时,它会通过底层的 Linux epoll 机制高效地阻塞等待,直到新消æ�¯åˆ°æ�¥æˆ–超时。这是 Looper.loop() ä¸�会空耗 CPU çš„åŽŸå› ã€‚

Looper:æ¯�个线程最多å�ªèƒ½æœ‰ä¸€ä¸ª Looper(通过 ThreadLocal å­˜å‚¨ï¼‰ã€‚å®ƒçš„æ ¸å¿ƒæ˜¯ loop() 方法,该方法进入一个死循环,ä¸�断地从其 MessageQueue 中å�–出下一æ�¡æ¶ˆæ�¯ï¼ˆqueue.next()),如果消æ�¯ä¸�为空,则将其分å�‘给消æ�¯çš„ç›®æ ‡ Handler(msg.target.dispatchMessage(msg))。

Handler:

创建:在哪个线程创建 Handler 实例,它默认就与该线程的 Looper 关�(除�显�指定 Looper)

å�‘é€�/å�‘布:æ��ä¾› post(Runnable)ã€�postDelayed()ã€�sendMessage()ã€�sendMessageDelayed()ã€�obtainMessage().sendToTarget() 等方法,将 Runnable 包装æˆ� Message 或直接将 Message æ”¾å…¥ç›®æ ‡ Looper çš„ MessageQueue 中

处ç�†ï¼šdispatchMessage(Message msg) 方法负责执行。如果 Message 有关è�”çš„ Runnable,则执行 Runnableï¼›å�¦åˆ™ï¼Œå¦‚æžœ Handler åˆ›å»ºæ—¶ä¼ å…¥äº† Callback 接å�£ï¼Œåˆ™è°ƒç”¨ callback.handleMessage();最å�Žï¼Œå¦‚æžœå‰�两者都没有,则调用 Handler å­�类覆写的 handleMessage(Message msg) 方法。执行å�‘生在与 Handler å…³è�”çš„ Looper 所在的线程上

ThreadLocal 的作用:Looper 使用 ThreadLocal(sThreadLocal)�确��个线程拥有自己独立的 Looper 实例。Looper.prepare() 就是�当�线程的 ThreadLocalMap 中存入一个新的 Looper 对象。

�典用途

�线程 → 主线程更新 UI:在�线程创建 new Handler(Looper.getMainLooper()),然�通过此 Handler post 一个更新 UI 的 Runnable。

创建自定义工作线程:

class WorkerThread extends Thread {

public Handler mHandler; // Handler for this worker thread

@Override

public void run() {

Looper.prepare(); // Associate a Looper with this thread

// Handler created here is associated with the new Looper

mHandler = new Handler(Looper.myLooper()) {

@Override

public void handleMessage(@NonNull Message msg) {

// Process messages received on this worker thread

Log.d("WorkerThread", "Processing message: " + msg.what);

}

};

Looper.loop(); // Start the message loop, blocks until Looper.quit()

Log.d("WorkerThread", "Looper finished.");

}

}

// Usage:

WorkerThread worker = new WorkerThread();

worker.start();

// Wait until handler is created (use CountDownLatch or similar for safety)

// ...

// Send messages from other threads to the worker thread's handler

worker.mHandler.obtainMessage(MSG_DO_WORK, someData).sendToTarget();

// ...

// To stop the worker thread's looper:

// worker.mHandler.getLooper().quitSafely(); // Or quit()

HandlerThread:Android �供的一个便利类,�装了上述创建带 Looper 的工作线程的逻辑。

常�陷阱

内存泄æ¼�:在 Activity/Fragment 中使用é�žé�™æ€�内部类 Handler,会导致 Handler éš�å¼�æŒ�有外部类引用。如果 Handler å�‘é€�了延迟消æ�¯ï¼Œå�³ä½¿ Activity 销æ¯�,消æ�¯ä»�在队列中,Handler å’Œ Activity éƒ½æ— æ³•è¢«å›žæ”¶ã€‚è§£å†³æ–¹æ¡ˆï¼šä½¿ç”¨é�™æ€�内部类 + WeakReference,或者使用 Lifecycle aware 组件

主线程 Looper 阻塞:在主线程 Handler 的 handleMessage 或 Runnable.run 中执行耗时�作

消�队列过载:过度��大�消��能导致处�延迟

七�高级�步与线程安全

当多个线程访问共享的��数�时,必须使用�步机制���数�的原�性(Atomicity)���性(Visibility) 和有�性(Ordering),防止出现数�竞争和�一致状�。

æ ¸å¿ƒæ¦‚å¿µ

原å­�性:一个æ“�作或者多个æ“�作è¦�么全部执行并且执行的过程ä¸�ä¼šè¢«ä»»ä½•å› ç´ æ‰“æ–­ï¼Œè¦�么就都ä¸�执行

��性:当一个线程修改了共享��的值,其他线程能够立�得知这个修改

有åº�性:程åº�执行的顺åº�按照代ç �的先å�Žé¡ºåº�执行(编译器和处ç�†å™¨å�¯èƒ½ä¼šè¿›è¡ŒæŒ‡ä»¤é‡�排优化,需è¦�å�Œæ­¥æœºåˆ¶æ�¥ä¿�è¯�特定情况下的有åº�性)

�步原语(Primitives)选择与应用

synchronized(内置�)

优点:使用简�,�易出错(自动释放�)

缺点:功能相对有�——�是��中断的;�支�公平性;一个��能关�一个�件等待队列。适用于简��低竞争的场景

volatile

作用:��被修饰��的��性;�止指令�排�优化(部分��有�性)

局�:���原�性。例如 volatile int i; i++; �是原��作

适用:主è¦�用于状æ€�æ ‡å¿—ä½�(如 volatile boolean flag = false;)或确ä¿�å�•次读写æ“�作的å�¯è§�性。ä¸�能替代é”�用于ä¿�护å¤�å�ˆæ“�作

java.util.concurrent.locks.Lock(如 ReentrantLock)

优点:功能更强——�中断�(lockInterruptibly);�超时�(tryLock);�实现公平/�公平�;�关�多个 Condition 对象(用于实现更��的等待/通知模�)

缺点:必须手动在 finally �中释放�(unlock()),�则�能导致死�

适用:需�更�活的�控制��中断性�公平性或多个等待�件的场景。性能在低竞争下与 synchronized 类似,高竞争下通常更好(但具体�决于实现和平�)

ReadWriteLock(如 ReentrantReadWriteLock)

场景:读多写少的共享数�。�许多个读线程�时访问,但写�作是互斥的

优点:显著�高读�作的并�性

注�:实现比 ReentrantLock 更��,需�正确使用读�(readLock())和写�(writeLock())

java.util.concurrent.atomic.*

场景:对å�•个å�˜é‡�(计数器ã€�状æ€�æ ‡å¿—ï¼‰è¿›è¡ŒåŽŸå­�æ›´æ–°

原ç�†ï¼šåˆ©ç”¨ CPU æ��供的 CAS(Compare-and-Swap)原å­�æŒ‡ä»¤å®žçŽ°ï¼Œæ— é”�(Lock-Free),效率高

优点:比使用�更轻��性能更好

局�:�能���个��的原�性,�能�����作的原�性

CountDownLatch

场景:一个线程需�等待一个或多个其他线程完��些�作��能继续执行。例如,主线程等待多个�始化�任务完�

CyclicBarrier

场景:多个线程需�相互等待,直到所有线程都到达一个「�障点�,然��能一起继续执行下一步。�以�用。例如,并行计算中,�阶段需�等待所有线程完�

Semaphore(信��)

场景:控制å�Œæ—¶è®¿é—®æŸ�个特定资æº�(如数æ�®åº“è¿žæŽ¥æ± ã€�网络连接数)的线程数é‡�

BlockingQueue

场景:生产者-消费者模�。解耦生产者线程和消费者线程,自带�步和阻塞功能

线程安全最佳实践

优先考虑ä¸�å�¯å�˜æ€§ï¼ˆImmutability):如果共享数æ�®æ˜¯ä¸�å�¯å�˜çš„(创建å�Žçжæ€�ä¸�å†�改å�˜ï¼‰ï¼Œåˆ™å¤©ç”Ÿçº¿ç¨‹å®‰å…¨ï¼Œæ— 需å�Œæ­¥

缩å°�å�Œæ­¥èŒƒå›´ï¼šå°½é‡�å‡�å°�é”�ä¿�护的代ç �å�—范围,å�ªä¿�护必è¦�的临界区,以æ��高并å�‘性

�顺�:如果需�获�多个�,确�所有线程都以相�的固定顺�获��,以��死�

使用并�容器:java.util.concurrent 包�供了线程安全的集�类(如 ConcurrentHashMap�CopyOnWriteArrayList),通常比手动�步 HashMap/ArrayList 更高效�更安全

é�¿å…�æŒ�有é”�时执行耗时æ“�作或调用外部方法:防止长时间å� 用é”�

八�ANR(Application Not Responding)深度分�

ANR 是 Android 中指示应用严é‡�æ— å“�应的信å�·ï¼Œæ˜¯å¿…须能够熟练诊断和解决的问题。

触��件回顾

输入事件超时:5 秒内未处�完输入事件(触摸�按键)

广播接收器超时:onReceive() 执行时间过长(��广播通常 10 秒,��广播�能 60 秒)

Service 超时:onCreate()�onStartCommand()�onBind() 等关键方法执行时间过长(���务 20 秒,���务�能 200 秒)

系统性分�步骤

1. 获� ANR Trace 文件

这是最��的��。�以从 /data/anr/traces.txt(需� root 或通过 adb bugreport),或 Google Play Console ��获�。

2. 识别 ANR 类型与时间

查看 Trace 文件开头的摘�信�,确认是哪�类型的 ANR(Input timeout�Broadcast timeout�Service timeout)以��生时间。

3. 主线程(“main�)状�分�

这是分æž�çš„æ ¸å¿ƒï¼� 仔细检查「mainã€�çº¿ç¨‹çš„å †æ ˆä¿¡æ�¯ï¼š

阻塞点:它最终�在了哪个方法调用上?

IO æ“�作? 是å�¦åœ¨è¿›è¡Œæ–‡ä»¶è¯»å†™ã€�网络请求ã€�æ•°æ�®åº“æ“�ä½œï¼ˆçœ‹å †æ ˆä¸­æ˜¯å�¦æœ‰nativePollOnceã€�socketReadã€�FileInputStream.readã€�SQLiteDatabase 相关调用)?

CPU 密集计算? å †æ ˆæ˜¯å�¦æ˜¾ç¤ºæ­£åœ¨æ‰§è¡Œå¤�æ�‚的计算逻辑?

�等待? 是��在 monitor wait 或 LockSupport.park / Object.wait 等待�?Trace 中通常会显示「waiting to lock <0x…>(a …)�以�「held by threadid=�

Binder 调用? 是å�¦å�¡åœ¨ BinderProxy.transactNative 或 binder_thread_read?如果是,看调用的是哪个æœ�åŠ¡ï¼ˆé€šå¸¸èƒ½ä»Žå †æ ˆæˆ– Binder 相关信æ�¯çœ‹å‡ºï¼‰ã€‚å¦‚æžœç›®æ ‡æ˜¯ç³»ç»Ÿæœ�务,需è¦�怀疑 SystemServer 是å�¦ç¼“慢或死é”�

GC? å †æ ˆæ˜¯å�¦æ˜¾ç¤ºæ­£åœ¨è¿›è¡Œ GC 相关æ“�作?(虽然 GC 本身引起的 ANR 相对少è§�,但长 GC æš‚å�œå�¯èƒ½åŠ å‰§å…¶ä»–è¶…æ—¶ï¼‰

4. 分���有者线程

如果主线程在等待é”�ï¼Œæ ¹æ�® Trace 中æ��供的æŒ�有者线程 ID(tidï¼‰ï¼Œæ‰¾åˆ°è¯¥çº¿ç¨‹çš„å †æ ˆã€‚åˆ†æž�该线程为什么长时间æŒ�有é”�?它是å�¦ä¹Ÿåœ¨è¿›è¡Œ IOã€�计算ã€�等待其他é”�(形æˆ�æ­»é”�链)ã€�或进行 Binder 调用?

5. 分� Binder 线程

检查所有å��为「Binder:_ã€�çš„çº¿ç¨‹å †æ ˆã€‚æ˜¯å�¦æœ‰ Binder 线程å�¡åœ¨è€—æ—¶çš„ onTransact 实现中?或者它们是å�¦ä¹Ÿåœ¨ç­‰å¾…é”�?

6. 检查其他线程

æµ�览其他å�Žå�°çº¿ç¨‹çš„å †æ ˆï¼Œçœ‹æ˜¯å�¦æœ‰å¼‚常活动,如å�‚与死é”�ã€�消耗过多 CPU 资æº�导致主线程饥饿等。

7. CPU 负载分�

查看 Trace 文件末尾的 CPU 负载信æ�¯ï¼ˆåˆ† User/Kernel/IOwait/IRQ/SoftIRQ)。高 User% å�¯èƒ½æ„�味 CPU 密集计算。高 IOwait% æ„�味ç£�盘或网络 IO 瓶颈。高 Kernel% å�¯èƒ½ä¸Žé©±åŠ¨æˆ–ç³»ç»Ÿè°ƒç”¨æœ‰å…³ã€‚æ£€æŸ¥ ANR å�‘生时主线程所在 CPU æ ¸å¿ƒæ˜¯å�¦ç¹�忙。

8. �信�分�

仔细阅读 Trace 文件中的 Locks 部分,它会列出所有�生争用的�以�等待和�有线程的信�,是分�死�的关键。

9. 结� Systrace/Perfetto

强烈推�� 如果能在�现 ANR 场景时抓� Trace,将�大简化分�。Perfetto/Systrace �以:

å�¯è§†åŒ–线程状æ€�:清晰看到主线程在 ANR å�‘生å‰�长时间处于 Runnable(等待 CPU 调度)还是 Running(执行代ç �)还是 Sleeping/Blocked 状æ€�

定ä½�耗时代ç �:结å�ˆ CPU Time Profiling,直接定ä½�到主线程或é”�æŒ�有者线程中耗时最长的方法

分��竞争:直观展示�的�有和等待关系

分æž� Binder 调用:显示 Binder äº‹åŠ¡çš„è€—æ—¶å’Œç›®æ ‡

关�系统事件:查看 GC�系统�务活动是�与 ANR 相关

��结论:掌控并�,驾驭�应

Android 的进程和线程模型是其并�架构的基础,直接关系到应用的资�消耗�稳定性与用户体验。从 Linux 的底层机制,到 Android 系统通过 AMS 和 oom_adj 对进程生命周期的精细管�,�到应用内部主线程�Binder 线程���线程的�责划分与��,以� Handler/Looper 机制和���步原语的应用,共�构�了这个��而��的体系。

Android 专家必须超越基础的线程使用,深刻ç�†è§£è¿›ç¨‹ä¼˜å…ˆçº§ä¸Ž LMK 的交互,掌æ�¡ä¸»çº¿ç¨‹çš„æ€§èƒ½çº¢çº¿ï¼Œç†Ÿæ‚‰ Binder çº¿ç¨‹æ± çš„è¿�ä½œï¼Œèƒ½å¤Ÿæ ¹æ�®åœºæ™¯é€‰æ‹©æœ€ä¼˜çš„å�Žå�°å¹¶å�‘策略(如 ExecutorServiceã€�Coroutines),精通 Handler 机制的内部原ç�†ä¸Žåº”用,并能够熟练è¿�用å�„ç§�高级å�Œæ­¥å·¥å…·è§£å†³å¤�æ�‚的线程安全问题。更é‡�è¦�的是,é�¢å¯¹ ANR 这一顽疾,能够è¿�用系统性的方法,结å�ˆ ANR Trace å’Œ Perfetto 等工具,抽ä¸�剥茧,定ä½�并解决从应用代ç �到系统æœ�务交互中å�¯èƒ½å­˜åœ¨çš„å�„ç§�性能瓶颈和死é”�问题。

对进程与线程模型的深度掌控,ä¸�仅是é�¿å…� ANR 的技术ä¿�障,更是实现高性能ã€�高并å�‘ã€�高稳定性应用,从而æ��ä¾›å�“è¶Šç”¨æˆ·ä½“éªŒçš„æ ¸å¿ƒèƒ½åŠ›ã€‚

延伸阅读

返回对应专题:Android Framework

Android Binder 原�:从驱动通信到 AIDL 调用链路/)

Android Framework 系统�务:AMS�WMS 与应用进程交互模型

Android ContentProvider 原�:URI 路由�跨进程访问与��控制

Android ��系统原�:�行时���拦截链路与安全边界

深圳曾经是个神童,是按照某种设计建设出来的人造城市;
矿卡到底能不能买?从业者说清风险与识别方法