CountDownLatch与Binder连接池
CountDownLatch
如果现在有一个题,有5个数,这时候我想让这5个数同时都乘2,然后算出结果后再算它们的平均数
这时候就可以用CountDownLatch
import java.util.concurrent.CountDownLatch;
public class Example {
public static void main(String[] args) throws InterruptedException {
int[] data = {1, 2, 3, 4, 5};
int numTasks = 5;
CountDownLatch latch = new CountDownLatch(numTasks);
double[] results = new double[numTasks];
for (int i = 0; i < numTasks; i++) {
final int taskId = i;
new Thread(() -> {
// 模拟任务处理过程
double result = data[taskId] * 2.0;
results[taskId] = result;
latch.countDown();
}).start();
}
// 等待所有任务完成
latch.await();
// 计算平均值
double sum = 0.0;
for (double result : results) {
sum += result;
}
double avg = sum / numTasks;
System.out.println("Average: " + avg);
}
我们定义了个数组,这个数组存放了{1,2,3,4,5}
然后我们
CountDownLatch latch = new CountDownLatch(numTasks);
让这5个同时开始
double[] results = new double[5];
然后开一个线程让data[i]中的每个元素乘以2.0
要是其中有一个完成了任务便会执行
latch.countDown();
进行减一操作,当计数器的值减到 0 时,主线程就会从 await() 方法中返回,可以开始计算平均值。
Binder连接池
在Binder连接池中,我们也会用到CountDownLatch
Binder连接池主要是解决AIDL中AIDL过多导致Service过多,让程序运行太慢
它让所有AIDL在一个Service中
比如我要弄一个加密代码,解密代码和加法运算
Aidl
interface ISecurityCenter {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
String encrypt(String content);
String decrypt(String password);
}
定义了这个接口用来加密和解密
interface ICompute {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
int add(int a , int b);
}
这个是用来进行加法运算
然后再定义一个查询接口
interface IBinderPool {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
IBinder queryBinder(int binderCode);
}
Service
public class BinderPoolService extends Service {
private Binder mBinderPool = new BinderPoolImpl();
public BinderPoolService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
return mBinderPool;
}
//
public static class SecurityCenterImpl extends ISecurityCenter.Stub{
//加密
private static final char SECRET_CODE = '^';
@Override
public 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);
}
//解密
@Override
public String decrypt(String password) throws RemoteException {
return encrypt(password);
}
}
public static class ComputeImpl extends ICompute.Stub{
@Override
public int add(int a, int b) throws RemoteException {
return a+b;
}
}
public class BinderPoolImpl extends IBinderPool.Stub{
@Override
public IBinder queryBinder(int binderCode) throws RemoteException {
IBinder binder = null;
switch (binderCode){
case 0:
binder = new SecurityCenterImpl();
break;
case 1:
binder = new ComputeImpl();
break;
default:
break;
}
return binder;
}
}
}
service端还比较简单,基本就和aidl那块一样
然后是Binder连接池
Binder连接池
public class BinderPoolClient {
private Context mContext;
private IBinderPool mIBinderPool;
private static volatile BinderPoolClient sInstance;
private CountDownLatch mConnectBinderPoolCountDownLatch;
public BinderPoolClient(Context context) {
mContext = context.getApplicationContext();
connectBinderPoolService();
}
public static BinderPoolClient getInstance(Context context){
if(sInstance==null){
synchronized (BinderPoolClient.class) {
if(sInstance==null) {
sInstance = new BinderPoolClient(context);
}
}
}
return sInstance;
}
private synchronized void connectBinderPoolService(){
mConnectBinderPoolCountDownLatch = new CountDownLatch(1);
Intent service = new Intent(mContext,BinderPoolService.class);
mContext.bindService(service,mBinderPoolConnection,Context.BIND_AUTO_CREATE);
try {
mConnectBinderPoolCountDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private ServiceConnection mBinderPoolConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIBinderPool = IBinderPool.Stub.asInterface(service);
try {
mIBinderPool.asBinder().linkToDeath(mBinderPoolDeathRecipient,0);
} catch (RemoteException e) {
e.printStackTrace();
}
mConnectBinderPoolCountDownLatch.countDown();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
private IBinder.DeathRecipient mBinderPoolDeathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.d("TAG","binder died");
mIBinderPool.asBinder().unlinkToDeath(mBinderPoolDeathRecipient,0);
mIBinderPool = null;
connectBinderPoolService();
}
};
public synchronized IBinder queryBinder(int binderCode){
IBinder iBinder = null;
try {
iBinder = mIBinderPool.queryBinder(binderCode);
} catch (RemoteException e) {
e.printStackTrace();
}
return iBinder;
}
}
Client
aidlPool.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
doWork();
}
});
thread.start();
//
}
});
private void doWork(){
BinderPoolClient binderPoolClient = BinderPoolClient.getInstance(MainActivity.this);
IBinder binder = binderPoolClient.queryBinder(0);
ISecurityCenter iSecurityCenter = BinderPoolService.SecurityCenterImpl.asInterface(binder);
Log.d("TAG","visit ISecurityCenter");
String msg = "helloworld-Android";
Log.d("TAG",msg);
try {
String password = iSecurityCenter.encrypt(msg);
Log.d("TAG","encrypt:"+password);
Log.d("TAG","decrypt:"+iSecurityCenter.decrypt(password));
} catch (RemoteException e) {
e.printStackTrace();
}
Log.d("TAG","visit ICompute");
IBinder binder1 = binderPoolClient.queryBinder(1);
ICompute iCompute = BinderPoolService.ComputeImpl.asInterface(binder1);
try {
Log.d("TAG","add"+iCompute.add(4,5));
} catch (RemoteException e) {
e.printStackTrace();
}
}