Binder Driver浅析:Binder线程池
线程池机制
大致流程
每个业务模块创建自己的AIDL接口并实现此接口,这个时候不同业务模块之间不能有耦合,所有实现细节单独开来,然后向服务端提供自己的唯一标识和其对应的Binder对象;对于服务端而言,只需要一个Service就可以了,服务端提供一个queryBinder接口,这个接口能够根据业务模块的特征来返回相应的Binder对象给它们,不同的业务模块拿到所需的Binder对象后就可以进程远程方法调用了。由此可见,Binder线程池的主要作用就是将每个业务模块的Binder请求统一转发到远程Servie中去执行,从而避免了重复创建Service的过程,工作原理如图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oqmhUvTK-1609320502667)(//upload-images.jianshu.io/upload_images/1126479-1b601d0e4ec62718.png?imageMogr2/auto-orient/strip|imageView2/2/w/622/format/webp)]
下面用代码模拟实现下。
我们创建两个AIDL接口(ISecurityCenter和ICompute)来模拟两个业务,多个时类似,增加对应接口即可。
ISecurityCenter.aidl
// ISecurityCenter.aidl
package com.breezehan.ipc.binderpool;interface ISecurityCenter {String encrypt(String content);String decrypt(String password);
}
ICompute.aidl
// ICompute.aidl
package com.breezehan.ipc.binderpool;interface ICompute {int add(int a,int b);
}
简单实现实现上述接口:
public class SecurityCenterImpl extends ISecurityCenter.Stub {private static final char SECRET_CODE = '^';@Overridepublic String encrypt(String content) throws RemoteException {char[] chars = content.toCharArray();for (int i = 0; i < chars.length; i++) {chars[i] ^= SECRET_CODE;}return new String(chars);}@Overridepublic String decrypt(String password) throws RemoteException {return encrypt(password);}
}
public class ComputeImpl extends ICompute.Stub {@Overridepublic int add(int a, int b) throws RemoteException {return a + b;}
}
业务模块都有了,我们要创建一个Binder连接池需要的AIDL,这里是一个代理或工厂,根据标识返回对应Binder
// IBinderPool.aidl
package com.breezehan.ipc.binderpool;interface IBinderPool {IBinder queryBinder(int binderCode);
}
在连接池中实现,根据标识返回不同Binder
static class BinderPoolImpl extends IBinderPool.Stub {@Overridepublic IBinder queryBinder(int binderCode) throws RemoteException {IBinder binder =null;switch (binderCode) {case BINDER_COMPUTE:binder = new ComputeImpl();break;case BINDER_SECURITY_CENTER:binder = new SecurityCenterImpl();break;}return binder;}
}
Service比较简单,逻辑处理都放在Binder线程池中
package com.breezehan.ipc.binderpool;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;public class BinderPoolService extends Service {private static final String TAG = "BinderPoolService";private IBinder binderPool = new BinderPool.BinderPoolImpl();public BinderPoolService() {}@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "onBind");return binderPool;}@Overridepublic void onDestroy() {super.onDestroy();}
}
Binder线程池的具体实现,同时需处理Binder死亡代理问题。
public class BinderPool {private static final String TAG = "BinderPool";public static final int BINDER_NONE = -1;public static final int BINDER_COMPUTE = 0;public static final int BINDER_SECURITY_CENTER = 1;private static volatile BinderPool sInstance;//确保并发取值正确性private final Context mContext;//控制多个线程时,某一线程中代码执行顺序;是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行private CountDownLatch mConnectBinderPoolCountDownLatch;private IBinderPool mBinderPool;public BinderPool(Context context) {mContext = context.getApplicationContext();connectBinderPoolService();}private void connectBinderPoolService() {mConnectBinderPoolCountDownLatch = new CountDownLatch(1);Intent service = new Intent(mContext, BinderPoolService.class);mContext.bindService(service, mServiceConnection, Context.BIND_AUTO_CREATE);try {mConnectBinderPoolCountDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}}public static BinderPool getInstance(Context context) {if (sInstance == null) {synchronized (BinderPool.class) {if (sInstance == null) {sInstance = new BinderPool(context);}}}return sInstance;}private ServiceConnection mServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mBinderPool = IBinderPool.Stub.asInterface(service);try {mBinderPool.asBinder().linkToDeath(mBinderDeathRecipient, 0);} catch (RemoteException e) {e.printStackTrace();}mConnectBinderPoolCountDownLatch.countDown();}@Overridepublic void onServiceDisconnected(ComponentName name) {}};private IBinder.DeathRecipient mBinderDeathRecipient = new IBinder.DeathRecipient() {@Overridepublic void binderDied() {Log.w(TAG, "binderDied: ");mBinderPool.asBinder().unlinkToDeath(mBinderDeathRecipient, 0);mBinderPool = null;connectBinderPoolService();}};public IBinder queryBinder(int bindCode) {IBinder binder = null;try {binder = mBinderPool.queryBinder(bindCode);} catch (RemoteException e) {e.printStackTrace();}return binder;}static class BinderPoolImpl extends IBinderPool.Stub {@Overridepublic IBinder queryBinder(int binderCode) throws RemoteException {IBinder binder =null;switch (binderCode) {case BINDER_COMPUTE:binder = new ComputeImpl();break;case BINDER_SECURITY_CENTER:binder = new SecurityCenterImpl();break;}return binder;}}
}
Activity中模拟使用。此处我只使用了其中一个Binder。
public class BinderPoolActivity extends AppCompatActivity {private static final String TAG = "BinderPoolActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_binder_pool);new Thread(new Runnable() {@Overridepublic void run() {doWork();}}).start();}private void doWork() {BinderPool binderPool = BinderPool.getInstance(BinderPoolActivity.this);IBinder securityBinder = binderPool.queryBinder(BinderPool.BINDER_SECURITY_CENTER);
// ISecurityCenter iSecurityCenter = ISecurityCenter.Stub.asInterface(securityBinder);ISecurityCenter iSecurityCenter = SecurityCenterImpl.asInterface(securityBinder);Log.d(TAG, "visit ISecurityCenter");String msg = "helloworld-安卓";try {String encrypt = iSecurityCenter.encrypt(msg);Log.d(TAG, "doWork,encrypt:"+encrypt);Log.d(TAG, "doWork,decrypt:"+iSecurityCenter.decrypt(encrypt));} catch (RemoteException e) {e.printStackTrace();}IBinder computeBinder = binderPool.queryBinder(BinderPool.BINDER_COMPUTE);ICompute iCompute = ComputeImpl.asInterface(computeBinder);try {Log.d(TAG, "doWork,compute: "+iCompute.add(1,2));} catch (RemoteException e) {e.printStackTrace();}}@Overrideprotected void onDestroy() {super.onDestroy();}
}
基本思想如上,改进或者多个Binder根本不变,添枝加叶即可。
选中合适的IPC方式
每种IPC方式都有优缺点和适用场景。
名称 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
Bundle | 简单易用 | 只能传输Bundle支持的数据类型 | 四大组件间的进程间通信 |
文件共享 | 简单易用 | 不适合高并发场景,并且无法做到进程间的即时通信 | 无并发访问情形,交换简单的数据,实时性不高的场景 |
AIDL | 功能强大,支持一对多并发通信,支持实时通信 | 使用稍复杂,需要处理好线程同步 | 一对多通信且有RPC需求 |
Messenger | 功能一般,支持一对多串行通信,支持实时通信 | 不能很好处理高并发情形,不支持RPC,数据通过Message进行传输,因此只能传输Bundle支持的数据类型 | 低并发的一对多即时通信,无RPC需求,或者无需要返回结果的RPC请求 |
ContentProvider | 在数据源访问方便功能强大,支持一对多并发数据共享,可通过Call方法扩展其他操作 | 可以理解为受约束的AIDL,主要提供数据源的CRUD操作 | 一对多的进程间的数据共享 |
Socket | 功能强大,可以通过网络传输字节流,支持一对多并发实时通信 | 实现细节稍微有点儿繁琐,不支持直接的RPC | 网络数据交换 |
Binder Driver浅析:Binder线程池相关推荐
- 【源码阅读计划】浅析 Java 线程池工作原理及核心源码
[源码阅读计划]浅析 Java 线程池工作原理及核心源码 为什么要用线程池? 线程池的设计 线程池如何维护自身状态? 线程池如何管理任务? execute函数执行过程(分配) getTask 函数(获 ...
- 浅析Java线程池 ExecutorService
ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中. 创建一个什么样的ExecutorService的实例(即线程池)需要g根据具体应用场 ...
- Binder系列1 Binder总体设计思想
Binder 是 Android 系统进程间通信(IPC)最主要的一种方式.Linux 已经拥有管道,system V IPC,socket 等 IPC 手段,Android 却还要使用专门的 Bin ...
- Android Binder机制(1):Binder架构分析
从这篇博客开始,将进入Binder机制的分析系列,顺序是先讲解Binder机制的框架,理解了整体思想后,再深入分析各层的细节实现,最后会实现一个自己的本地服务. 1.Binder的历史 BeOS是Be ...
- 由浅入深 学习 Android Binder(十一) binder线程池
Android Binder系列文章: 由浅入深 学习 Android Binder(一)- AIDL 由浅入深 学习 Android Binder(二)- bindService流程 由浅入深 学习 ...
- Android Binder机制浅析及AIDL的使用
参考 轻松理解 Android Binder,只需要读这一篇 图文详解 Android Binder跨进程通信的原理 Android中的Parcel是什么 Android Binder IPC通信机制 ...
- Android Binder Driver流程分析
Binder是Android中使用最为广泛的IPC框架,从实现的角度可以分为内核层和用户空间层,本文主要分析下Binder Driver在内核层的实现. Binder Driver初始化 1 2 3 ...
- Android 进阶8:进程通信之 Binder 机制浅析
读完本文你将了解: IBinder Binder Binder 通信机制 Binder 驱动 Service Manager Binder 机制跨进程通信流程 Binder 机制的优点 总结 Than ...
- Android Binder Driver缺陷导致定屏问题分析
本文讲解异步Android binder call是如何阻塞整个系统的,通过ramdump信息以及binder通信协议来演绎并还原定屏现场. 一.背景知识点 解决此问题所涉及到的基础知识点有:Trac ...
最新文章
- js字母大小写字母转换
- 5G NR — 密集组网和异构组网
- [c/c++] programming之路(28)、结构体存储和内存对齐+枚举类型+typedef+深拷贝和浅拷贝...
- 11月27日struts项目练习评审
- POJ2369 置换群
- floyed java_Floyd算法java实现demo
- ant的设置properties
- 人机协同、数据驱动,云时代SOC的演进之路
- npm 查看登陆账号_自定义npm 及问题整理
- 古老的window程序设计
- ekho--TTS语音引擎
- 网上好用的大数据支持的舆情分析系统工具整合
- python爬虫(十三)selenium(Selenium入门、chromedriver、Phantomjs)
- Installation failed due to: ‘‘cmd package install-create -r -t --user current --full --dont-kill -t
- 计算机使用技巧大全 书,总算明白电脑使用技巧大全
- Unnecessary escape character: \- no-useless-escape eslint
- Kali 获取WEP无线密码过程
- android 根文件系统,Android根文件系统相关应用介绍
- 决策树算法-理清每个细节-附R+Python代码
- hp笔记本的计算机在哪里,惠普电脑型号在哪里看
热门文章
- mysql 非等值条件 索引_mysql 索引学习--多条件等值查询,顺序不同也能应用联合索引啦...
- mysql支持的并发数_重学MySQL系列(五):谈谈对MySQL的存储引擎的理解
- html如何实现新闻标题缩略,CSS新闻标题后面跟着new图标_CSS实例
- 英特尔的指令集体系结构_对标英特尔的RISC-V大有可为,CPU三分天下格局可期
- 从java到c_Binder机制,从Java到C (4. Parcel)
- python调用c++动态库 linux_linux中使用boost.python调用c++动态库的方法
- mysql-Mac终端下遇到的问题总结
- Linux中的In命令
- Qt 5.5增加了新的GL模块,并改进了跨平台支持
- tcpdump + wireshark 抓包组合