1.进程和线程
进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一些在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

区别:
 ①一个程序至少有一个进程,一个进程至少有一个线程;
 ②线程的划分尺度小于进程,使得多线程程序的并发性高;
 ③进程在执行过程中拥有独立的内存单元,而多个线程共享内存,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉。

2.进程
当一个应用开始运行时,系统会为它创建一个进程,一个应用默认只有一个进程,这个进程(主进程)的名称就是应用的包名。

首先,进程一般指一个执行单元,在移动设备上就是一个程序或应用,我们在Android中所说的多进程(IPC)一般指一个应用包含多个进程。之所以要使用多进程有两方面原因:某些模块由于特殊的需求要运行在单独的进程;增加应用可用的内存空间。

进程的特点:
①进程是系统资源和分配的基本单位,而线程是调度的基本单位。
②每个进程都有自己独立的资源和内存空间
③其它进程不能任意访问当前进程的内存和资源④系统给每个进程分配的内存会有限制。
根据以上特点可以看出,使用多进程的场景为:需要使apk所使用的内存限制扩大。

进程的等级:
进程按优先级可以分为五类,优先级从高到低排列:

①前台进程:该进程包含正在与用户进行交互的界面组件,比如一个Activity。在接收关键生命周期方法时会让一个进程临时提升为前台进程,包括任何服务的生命周期方法onCreate()和onDestroy()和任何广播接收器onReceive()方法。这样做确保了这些组件的操作是有效的原子操作,每个组件都能执行完成而不被杀掉。
②可见进程:该进程中的组件虽然没有和用户交互,但是仍然可以被看到。activity可见的时候不一定在前台。一个简单的例子是前台的 activity 使用对话框启动了一个新的 activity 或者一个透明 activity 。另一个例子是当调用运行时权限对话框时(事实上它就是一个 activity!)。
③服务进程:该进程包含在执行后台操作的服务组件,比如播放音乐的Service。对于许多在后台做处理(如加载数据)而没有立即成为前台服务的应用都属于这种情况。
请特别注意从onStartCommand()返回的常量,如果服务由于内存压力被杀掉,它表示控制什么发生什么:
START_STICKY表示希望系统可用的时候自动重启服务,但不关心是否能获得最后一次的 Intent (例如,可以重建自己的状态或者控制自己的 start/stop 生命周期)。
START_REDELIVER_INTENT是为那些在被杀死之后重启时重新获得 Intent 的服务的,直到用传递给 onStartCommand() 方法的 startId 参数调用stopSelf()为止。这里会使用 Intent 和 startId 作为队列完成工作。
START_NOT_STICKY用于那些杀掉也没关系的服务。这适合那些管理周期性任务的服务,它们只是等待下一个时间窗口工作。
④后台进程:该进程包含的组件没有与用户交互,用户也看不到 Service。在一般操作场景下,设备上的许多内存就是用在这上面的,使可以重新回到之前打开过的某个 activity 。
⑤空进程:没有任何界面组件、服务组件,或触发器组件,只是出于缓存的目的而被保留(为了更加有效地使用内存而不是完全释放掉),只要 Android 需要可以随时杀掉它们。

多进程的创建:
Android开启多进程只有一种方法,就是在AndroidManifest.xml中注册Service、Activity、Receiber、ContentProvider时指定"android:process”属性即可。命名之后,就成了一个单独的进程。例如:
< service
android:name=".MyService"
android:process=":remote">
< /service>

< activity
android:name=".MyActivity"
android:process=“com.shh.ipctest.remote2”>
< /activity>

process分私有进程和全局进程:
①私有进程的名称前面有冒号,例如:
< service android:name=".MusicService"
android:process=":musicservice"/>
以:开头是一种简写,系统会在当前进程名前附上当前包名,完整的进程名为:com.shh.ipctest:musicservice。
以:开头的进程属于当前应用的私有进程,其它应用的组件不能和它跑在同一进程。
com.shh.ipctest.remote2:这是完整的命名方式,不会附加包名,其它应用如果和该进程的ShareUID、签名相同,则可以和它跑在同一个进程,实现数据共享。
②全局进程的名称前面没有冒号,例如:
< service android:name=".MusicService" android:process=“com.trampcr.musicdemo.service”/>
com.trample.music demo.service这是完整的命名方式,不会附加包名,其它应用如果和该进程的ShareUID、签名相同,则可以和它跑在同一个进程,实现数据共享。

多进程引发的问题:
开启多进程虽简单,但会引发如下问题,必须引起注意。
①静态成员和单例模式失效
②线程同步机制失效
③SharedPreferences 可靠性降低
④Application 被多次创建
对于前两个问题,可以这么理解,在Android中,系统会为每个应用或进程分配独立的虚拟机,不同的虚拟机自然占有不同的内存地址空间,所以同一个类的对象会产生不同的副本,导致共享数据失败,必然也不能实现线程的同步。
由于SharedPreferences底层采用读写XML的文件的方式实现,多进程并发的的读写很可能导致数据异常。
Application被多次创建和前两个问题类似,系统在分配多个虚拟机时相当于把同一个应用重新启动多次,必然会导致Application多次被创建,为了防止在 Application中出现无用的重复初始化,可使用进程名来做过滤,只让指定进程的才进行全局初始:
public class MyApplication extends Application{
@Override
public void onCreate() {
super.onCreate();
String processName = “com.shh.ipctest”;
if(getPackageName().equals( processName)){
// do some init
}

为了节省系统内存,在退出该Activity的时候可以将其杀掉(如果没有人为杀掉该进程,在程序完全退出时该进程会被系统杀掉)

3.进程间通信方式
同一个进程的多个线程是共享该进程的所有资源,但多个进程间内存是不可见的,也就是说多个进程间内存是不共享的。为了在不同应用程序之间交互数据(跨进程通讯),在android SDK中提供了4种用于跨进程通讯的方式。这4种方式正好对应于android系统中4种应用程序组件:Activity、Content Provider、Broadcast和Service。其中Activity可以跨进程调用其他应用程序的Activity;Content Provider可以跨进程访问其他应用程序中的数据(以Cursor对象形式返回),当然,也可以对其他应用程序的数据进行增、删、改操 作;Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播;Service和Content Provider类似,也可以访问其他应用程序中的数据,但不同的是,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。
①Intent(Bundle) 
由于Activity,Service,Receiver都是可以通过Intent来携带Bundle传输数据的,所以我们可以在一个进程中通过Intent将携带数据的Bundle发送到另一个进程的组件。bundle支持传输的类型很多,如基本类型、实现了Parcelable或Serializable接口的对象。  
缺点:无法传输Bundle不支持的数据类型。

Activity的跨进程访问与进程内访问略有不同。虽然它们都需要Intent对象,但跨进程访问并不需要指定Context对象和Activity的Class对象,而需要指定的是要访问的Activity所对应的Action(activity隐式调用)。有些Activity还需要指定一个Uri(通过 Intent构造方法的第2个参数指定)。
在android系统中有很多应用程序提供了可以跨进程访问的Activity,例如,下面的代码可以直接调用拨打电话的Activity。
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse(“tel:1234” );
startActivity(callIntent);

②ContentProvider  
ContentProvider是Android四大组件之一,以表格的方式来储存数据,提供给外界,即Content Provider可以跨进程访问其他应用程序中的数据。
用法是继承ContentProvider,实现onCreate,query,update,insert,delete和getType方法,onCreate是负责创建时做一些初始化的工作,增删查改的方法就是对数据的查询和修改,getType是返回一个String,表示Uri请求的类型。注册完后就可以使用ContentResolver去请求指定的Uri。

③文件
两个进程可以到同一个文件去交换数据,我们不仅可以保存文本文件,还可以将对象持久化到文件,从另一个文件恢复。要注意的是,当并发读/写时可能会出现并发的问题。

④广播Broadcast
Broadcast可以向android系统中所有应用程序发送广播,而需要跨进程通讯的应用程序可以监听这些广播。

⑤AIDL方式  
Service和Content Provider类似,也可以访问其他应用程序中的数据,Content Provider返回的是Cursor对象,而Service返回的是Java对象,这种可以跨进程通讯的服务叫AIDL服务。
AIDL通过定义服务端暴露的接口,以提供给客户端来调用,AIDL使服务器可以并行处理,而Messenger封装了AIDL之后只能串行运行,所以Messenger一般用作消息传递。

⑥Messenger  
Messenger是基于AIDL实现的,服务端(被动方)提供一个Service来处理客户端(主动方)连接,维护一个Handler来创建Messenger,在onBind时返回Messenger的binder。双方用Messenger来发送数据,用Handler来处理数据。Messenger处理数据依靠Handler,所以是串行的,也就是说,Handler接到多个message时,就要排队依次处理。

⑦Socket
Socket方法是通过网络来进行数据交换,注意的是要在子线程请求,不然会堵塞主线程。客户端和服务端建立连接之后即可不断传输数据,比较适合实时的数据传输。

3.线程间通信方式
线程间通信包括主线程(也叫UI线程)和子线程之间的通信、子线程之间的通信两种。下面分别介绍。

主线程与子线程之间的通信方式:
①AsyncTask机制  
AsyncTask,异步任务,也就是说在UI线程运行的时候,可以在后台执行一些异步的操作;AsyncTask可以很容易且正确地使用UI线程,AsyncTask允许进行后台操作,并在不显示使用工作线程或Handler机制的情况下,将结果反馈给UI线程。但是AsyncTask只能用于短时间的操作(最多几秒就应该结束的操作),如果需要长时间运行在后台,就不适合使用AsyncTask了,只能去使用Java提供的其他API来实现。

②Handler机制  
Handler,继承自Object类,用来发送和处理Message对象或Runnable对象。
Handler在创建时会与当前所在的线程的Looper对象相关联(如果当前线程的Looper为空或不存在,则会抛出异常,此时需要在线程中主动调用Looper.prepare()来创建一个Looper对象)。
使用Handler的主要作用就是在后面的过程中发送和处理Message对象和让其他的线程完成某一个动作(如在工作线程中通过Handler对象发送一个Message对象,让UI线程进行UI的更新,然后UI线程就会在MessageQueue中得到这个Message对象(取出Message对象是由其相关联的Looper对象完成的),并作出相应的响应)。

子线程之间的通信方式:
主线程和子线程之间的通信可以通过主线程中的handler把子线程中的message发给主线程中的looper,或者,主线程中的handler通过post向looper中发送一个runnable。但looper默认存在于main线程中,子线程中没有Looper,该怎么办呢?其实原理很简单,把looper绑定到子线程中,并且创建一个handler。在另一个线程中通过这个handler发送消息,就可以实现子线程之间的通信了。  
子线程创建handler的两种方式:  
方式一:给子线程创建Looper对象:
new Thread(new Runnable() {
public void run() {
Looper.prepare(); // 给这个Thread创建Looper对象,一个Thead只有一个Looper对象
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), “handleMessage”, Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
Looper.loop(); // 不断遍历MessageQueue中是否有消息
};
}).start();

方式二:获取主线程的looper,或者说是UI线程的looper:
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler(Looper.getMainLooper()){ // 区别在这!!!
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), “handleMessage”, Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
};
}).start();

Android 进程间通信方式和线程间通信方式相关推荐

  1. 面试题:进程间通信方式,线程间通信方式

    一.进程间通信(IPC,Inter-Process Communication)是指在不同进程间传播或交换信息 1. 无名管道 特点 半双工(数据流向仅有一个方向),具有固定的读端和写端 只能用于父进 ...

  2. 进程间通信方式和线程间通信方式

    进程间通信方式: 1.管道( pipe ): 管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系.缺点:速度慢,容量有限,只有父子进程 ...

  3. android线程间通信的几种方法_Android进程间和线程间通信方式

    进程:是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程:是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位 ...

  4. Linux的进程/线程间通信方式总结

    Linux系统中的进程间通信方式主要以下几种: 同一主机上的进程通信方式 * UNIX进程间通信方式: 包括管道(PIPE), 有名管道(FIFO), 和信号(Signal) * System V进程 ...

  5. Linux 线程间通信方式+进程通信方式

    1. linux下进程间通信的几种主要手段简介: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能 ...

  6. linux的进程与线程通信方式,Linux的进程/线程间通信方式总结

    Linux系统中的进程间通信方式主要以下几种: 同一主机上的进程通信方式 * UNIX进程间通信方式: 包括管道(PIPE), 有名管道(FIFO), 和信号(Signal) * System V进程 ...

  7. Python线程间通信方式

    1.python多线程 #! /usr/bin/evn python3 # --*-- coding: utf-8 --*--#该实例反编译来说明函数执行流程 import disdef add(a) ...

  8. 线程间通信方式Linux,线程间的通信、同步方式与进程间通信方式

    1.线程间的通信方式 使用全局变量 主要由于多个线程可能更改全局变量,因此全局变量最好声明为volatile 使用消息实现通信 在Windows程序设计中,每一个线程都可以拥有自己的消息队列(UI线程 ...

  9. android进、线程间通信方式

    1.进程间的通信 AIDL .Messager. Binder .Socket.File.ContentProvider.管道.Binder 2.线程间的通信 EventBus的使用 1.自定义一个类 ...

最新文章

  1. C# 语言规范_版本5.0 (第10章 类)
  2. iOS设计模式 - 生成器
  3. CSDN博客转载攻略
  4. javascript中三个等号的意思
  5. 多线程池、饱和策略详解
  6. Wide character in print at ../lib/MonWalkProc.pm line 569.
  7. arduino 中断 串口_【Arduino教程】第一讲:Arduino是什么?
  8. .net 事务嵌套存储过程事务的处理方法
  9. 武汉年会签到,抽奖,摇一摇,微信上墙,互动大屏
  10. 东芝 rc100 linux,入门级NVMe固态硬盘首选,东芝RC100带来的超值体验
  11. 创业公司必备,20个提升团队工作效率的工具神器
  12. html5的元素拖拽
  13. 网站服务器过期与域名备案,服务器到期了 域名备案受影响吗
  14. Timer定时器用法详解
  15. 直播答题狂撒币,这些“AI开挂神器”如何在10秒内算出正确答案?
  16. stable diffusion图片转图片(教程)
  17. js和jquery实现页面跳转的几种方式
  18. Topic Modeling of Short Texts: A Pseudo-Document View
  19. Java数字化智慧校园平台源码,智慧学校源码+微信小程序+人脸电子班牌
  20. 用户界面设计10原则 (转)

热门文章

  1. android NDK 之cmake的使用
  2. XLINX系列之Zynq-7000系列有哪些中断?
  3. Xlinx Zynq7035 PL SFP光口通信例程
  4. 基于asp.net703宠商城网站宠物系统
  5. 《球机的PTZ和视场角与ONVIF的PTZ对应关系》
  6. cad二次开发-在vs编译软件环境下使用c#语言编写dll文件-新建图层
  7. Android连接多个ble设备
  8. jsp21127无人超市采购购物系统
  9. html 右上角图标r,html Rmarkdown中上图的标题
  10. 多线程+Race Condition现象及产生的原因