【Android多线程】线程二三事

Android中线程大致可分为3类:UI线程,Binder线程和Background线程。

UI Thread

UI线程也就是我们常说的主线程(Main Thread),在App启动时默认被创建,主要是负责UI的显示、更新和控件交互。Android中UI的更新只允许在UI线程完成,这是因为Android UI Toolkit并非线程安全(且实现线程安全也是一件非常困难的事情),所以Android运行时通过只允许UI线程更新UI的方式保证安全性。如果其他线程尝试更新UI,会得到CalledFromWrongThreadException。

Binder Thread

Binder是Android中特有的进程间通信(Intent-Process Communication)机制。Android中的进程可能需要响应来自其他进程的请求,比如系统服务(system service),内容提供器(content provider)等。这时Binder线程会被自动创建用于进程间的消息传递。通常App本身并不需要关心Binder线程,因为来自其他进程的消息都会被转到UI线程,比如Service的各种回调,除非是App自己定义的AIDL(Android Interface Definition Language)接口。

Background Thread

所有App显式创建的线程都属于后台线程。这里所谓的UI Thread和Background Thread的概念属于Android特有的特性(Androidisms),主要用来区分是否可以更新UI。这些线程本身对于Linux并没有区别,更新UI的限制也是通过Android Application Framework中的Window Manager实现的。

 

查看线程

可以通过ps查看手机中的进程,即Linux中通过加载二进制可执行文件而运行起来的进程:

adb shell ps

部分截图:

【Android多线程】线程二三事_第1张图片

【Android多线程】线程二三事_第2张图片

一些主要的概念:

  • USER:Android继承了Linux的权限方式,通过"用户(User)"和"组(Group)"的概念进行权限控制。不同的是,Android中用户是分配给各个应用而非给使用系统的人。一个用户(即App)不能访问另一个用户的文件,目录或是进程。
  • PID:进程ID(其实为status中的Tgid)
  • PPID:父进程ID
  • S:当前状态,有如下几种: R (running),S (sleeping),D (device I/O),T (stopped) ,t (traced),Z (zombie) ,X (deader) ,x (dead) ,K (wakekill),W (waking)

可以通过-T查看线程,比如查看Google Maps(u0_a84):

 adb shell ps -T -U u0_a84

【Android多线程】线程二三事_第3张图片

TID即为线程ID,通常主线程TID和PID是相等的。

可以通过查看/proc/tgid/status文件获得更丰富的进程相关信息:

adb shell
cat /proc/18193/status

【Android多线程】线程二三事_第4张图片

这里的Tgid其实才是真正意义上的进程ID,PID实际表示当前读取的伪文件的线程ID。Linux以线程而非进程作为处理器调度的基本单位,进程在本质上是共享了一系列资源(虚拟内存地址,文件描述符等)的一组线程。不过可能因为PID作为“线程ID”难以理解,ps --help时解释PID实际仍为线程ID(Process ID)。

 

 

参考资料

  • 《Efficient Android Threading》
  • 《最强Android书:架构大剖析》

你可能感兴趣的:(【Android杂谈】)