android study 13
android中进程与线程
进程与线程的区别
1.线程是CPU调度的最小单元,同时线程本身是一种有限的系统资源
2.进程是一个执行单元,安卓中一个应用就是一个进程。进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,是CPU调度和分配的基本单位,是比进程更小的能独立运行的基本单位,线程本身不拥有系统资源(除了必不可少的资源如程序计数器、寄存器、栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
3.线程与进程主要差别在于是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其他进程产生影响,而线程是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的健壮,但是多进程在切换时,资源耗费大,效率要差。
主线程
我们知道,安卓应用启动流程中,实际是Zygote负责fork出子进程,并且执行ActivityThread.main()方法,main方法的调用就是在主线程/UI线程中。
主线程负责向UI组件分发事件(包括绘制事件),在这个进程中,安卓应用和安卓组件发生交互。所以主线程也叫做UI线程。系统不会为每个组件单独创建线程,在同一个进程里的UI组件都会在UI线程中实例化,系统对每一个组件的调用都从UI线程中分发出去。
响应系统回调的方法,比如响应用户的onKeyDown和各种生命周期回调,都是在UI线程里运行。
那么很容易理解,主线程是不能被阻塞的,应该把耗时任务放到单独的线程中去完成(如工作线程/后台线程)
安卓进程分类
安卓进程按应用组件及组件状态可以分为五个重要性等级:
1.前台进程:当前进程正在被用户请求服务的进程,满足以下条件:
*包含一个Activity正在和用户交互(Resume状态下)
*包含一个绑定到Activity的Service,这个Activity正在和用户交互
*包含一个前台Service,Service 调用了startForeground()方法
*包含一个正在执行onReceive的Receiver
前台进程优先级最高,是最后杀掉的对象。
2.可见进程:不包含前台组件,但是包含用户可见组件的进程(但是不可交互),满足以下条件:
*包含一个Activity处于onPause状态
*包含一个Service,这个Service绑定了可见Activity
3.Service进程:一个进程包含了Service,但是不包含前两种级别组件的进程
4.后台进程:一个进程包含Activity,但是这个Activity不再对用户可见,例如一个应用处于onStop状态。
5.空进程:进程中不存在活动组件。这种进程存在的目的是缓存作用,下次启动该应用时直接启动该进程。
因为一个运行着 service 的进程优先级比一个运行着后台 activity 的优先级高,这就是为什么要使用一个 service 来处理一个耗时的操作会比简单开启一个工作线程来处理要好的原因。也是为啥在广播中开启线程来处理操作比不上启动一个 service 来操作更保险的原因。
进程依赖
如果进程A依赖进程B,那么进程B的优先级永远更高。比如进程B的provider给进程A提供数据,或者进程B的Service给进程B某个组件绑定了。
安卓进程间通信方式对比
1.Intent通信,简单易用,但是只支持Bundle所支持的数据类型,用于四大组件间的进程间通信
2.文件共享,简单易用,但不适合高并发的场景,简单数据共享且无高并发场景使用
3.AIDL,功能强大,支持一对多并发实时通信,但是需要注意线程同步问题,用于复杂的进程间调用。
4.Messenger,比AIDL简单易用,但是只支持1对多串行实时通信,可以用于简单的进程间通信场景
5.ContentProvider,强大的数据共享能力,可以通过call方法扩展,受约束的AIDL,主要对外提供数据的CRUD操作,用于进程间大量数据共享的场景。
6.RemoteViews, 跨进程访问UI方面很有用,比较小众的通信方式,可以用于某些特殊场景
7.Socket,跨主机,通信范围广,但是只能传输字节流,常用于网络通信中
linux进程调度
操作系统是应用程序和可用资源之间的媒介,如内存,cpu,物理设备都是资源,调度器使得同时执行多个程序成为可能,可以让应用程序共享CPU。调度器讲CPU的时间片有效分配给应用程序,这其中会面临一些问题,比如要为关键实时任务最小化响应时间, 又要最大限度地提高 CPU 的总体利用率。
linux进程的分类
当涉及有关调度的问题时, 传统上把进程分类为”I/O受限(I/O-dound)”或”CPU受限(CPU-bound)”。
另外一种分类法把进程区分为三类: 交互式进程,批处理进程,实时进程
在linux中, 调度算法可以明确的确认所有实时进程的身份, 但是没办法区分交互式程序和批处理程序(统称为普通进程), linux2.6的调度程序实现了基于进程过去行为的启发式算法, 以确定进程应该被当做交互式进程还是批处理进程. 当然与批处理进程相比, 调度程序有偏爱交互式进程的倾向。
根据进程的不同分类Linux采用不同的调度策略。对于实时进程,采用FIFO或者Round Robin的调度策略。对于普通进程,则需要区分交互式和批处理式的不同。传统Linux调度器提高交互式应用的优先级,使得它们能更快地被调度。而CFS和RSDL等新的调度器的核心思想是”完全公平”。这个设计理念不仅大大简化了调度器的代码复杂度,还对各种调度需求的提供了更完美的支持.