线程池机制

大致流程

每个业务模块创建自己的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线程池相关推荐

  1. 【源码阅读计划】浅析 Java 线程池工作原理及核心源码

    [源码阅读计划]浅析 Java 线程池工作原理及核心源码 为什么要用线程池? 线程池的设计 线程池如何维护自身状态? 线程池如何管理任务? execute函数执行过程(分配) getTask 函数(获 ...

  2. 浅析Java线程池 ExecutorService

    ExecutorService是Java中对线程池定义的一个接口,它java.util.concurrent包中. 创建一个什么样的ExecutorService的实例(即线程池)需要g根据具体应用场 ...

  3. Binder系列1 Binder总体设计思想

    Binder 是 Android 系统进程间通信(IPC)最主要的一种方式.Linux 已经拥有管道,system V IPC,socket 等 IPC 手段,Android 却还要使用专门的 Bin ...

  4. Android Binder机制(1):Binder架构分析

    从这篇博客开始,将进入Binder机制的分析系列,顺序是先讲解Binder机制的框架,理解了整体思想后,再深入分析各层的细节实现,最后会实现一个自己的本地服务. 1.Binder的历史 BeOS是Be ...

  5. 由浅入深 学习 Android Binder(十一) binder线程池

    Android Binder系列文章: 由浅入深 学习 Android Binder(一)- AIDL 由浅入深 学习 Android Binder(二)- bindService流程 由浅入深 学习 ...

  6. Android Binder机制浅析及AIDL的使用

    参考 轻松理解 Android Binder,只需要读这一篇 图文详解 Android Binder跨进程通信的原理 Android中的Parcel是什么 Android Binder IPC通信机制 ...

  7. Android Binder Driver流程分析

    Binder是Android中使用最为广泛的IPC框架,从实现的角度可以分为内核层和用户空间层,本文主要分析下Binder Driver在内核层的实现. Binder Driver初始化 1 2 3 ...

  8. Android 进阶8:进程通信之 Binder 机制浅析

    读完本文你将了解: IBinder Binder Binder 通信机制 Binder 驱动 Service Manager Binder 机制跨进程通信流程 Binder 机制的优点 总结 Than ...

  9. Android Binder Driver缺陷导致定屏问题分析

    本文讲解异步Android binder call是如何阻塞整个系统的,通过ramdump信息以及binder通信协议来演绎并还原定屏现场. 一.背景知识点 解决此问题所涉及到的基础知识点有:Trac ...

最新文章

  1. js字母大小写字母转换
  2. 5G NR — 密集组网和异构组网
  3. [c/c++] programming之路(28)、结构体存储和内存对齐+枚举类型+typedef+深拷贝和浅拷贝...
  4. 11月27日struts项目练习评审
  5. POJ2369 置换群
  6. floyed java_Floyd算法java实现demo
  7. ant的设置properties
  8. 人机协同、数据驱动,云时代SOC的演进之路
  9. npm 查看登陆账号_自定义npm 及问题整理
  10. 古老的window程序设计
  11. ekho--TTS语音引擎
  12. 网上好用的大数据支持的舆情分析系统工具整合
  13. python爬虫(十三)selenium(Selenium入门、chromedriver、Phantomjs)
  14. Installation failed due to: ‘‘cmd package install-create -r -t --user current --full --dont-kill -t
  15. 计算机使用技巧大全 书,总算明白电脑使用技巧大全
  16. Unnecessary escape character: \- no-useless-escape eslint
  17. Kali 获取WEP无线密码过程
  18. android 根文件系统,Android根文件系统相关应用介绍
  19. 决策树算法-理清每个细节-附R+Python代码
  20. hp笔记本的计算机在哪里,惠普电脑型号在哪里看

热门文章

  1. mysql 非等值条件 索引_mysql 索引学习--多条件等值查询,顺序不同也能应用联合索引啦...
  2. mysql支持的并发数_重学MySQL系列(五):谈谈对MySQL的存储引擎的理解
  3. html如何实现新闻标题缩略,CSS新闻标题后面跟着new图标_CSS实例
  4. 英特尔的指令集体系结构_对标英特尔的RISC-V大有可为,CPU三分天下格局可期
  5. 从java到c_Binder机制,从Java到C (4. Parcel)
  6. python调用c++动态库 linux_linux中使用boost.python调用c++动态库的方法
  7. mysql-Mac终端下遇到的问题总结
  8. Linux中的In命令
  9. Qt 5.5增加了新的GL模块,并改进了跨平台支持
  10. tcpdump + wireshark 抓包组合