问题:
实现了AIDL接口的服务的方法是运行在哪个线程?有多个方法,是不是运行在同一个线程?
回答:
在AIDL服务端实现的方法一般情况下运行在服务端的Binder线程上,有多个方法时,运行在多个线程。
解析:
我们继续基于上文的测试代码进行分析,修改onServiceConnected,在成功获取Binder代理对象后,分别调用addBook和getBookList方法,代码如下所示:
@Override public void onServiceConnected(ComponentName name, IBinder service) {
IBookManager bookManager = IBookManager.Stub.asInterface(service);
Log.d(TAG,"获取到远端代理对象:"+bookManager);
try {
mRemoteBookManager = bookManager;
Book newBook = new Book(3, "学姐的故事");
Log.d(TAG,"BookManager called addBook function start");
bookManager.addBook(newBook);
Log.d(TAG,"BookManager called addBook function end");
Log.d(TAG,"BookManager called getBookList function start");
List<Book> books = bookManager.getBookList();
Log.d(TAG,"BookManager called getBookList function end");
} catch (RemoteException e) {
e.printStackTrace();
}
}
随后修改Server端的addBook和getBookList,打印执行该函数的线程名,代码如下:
@Override public List<Book> getBookList() throws RemoteException {
Log.d(TAG,"开始getBookList,thread is:"+Thread.currentThread().getName());
SystemClock.sleep(5000); // 延迟加载
Log.d(TAG,"getBookList end");
return mBookList;
}
@Override public void addBook(Book book) throws RemoteException {
Log.d(TAG,"开始添加book,thread is:"+Thread.currentThread().getName());
mBookList.add(book);
Log.d(TAG,"添加book完成");
}
运行后日志输出如下:
可以看出addBook和getBookList方法分别运行在Binder:2374_4和Binder:2374_2这两个Binder线程中。
结合上述示例可以看出,在Binder通信机制中,Server端有一个Binder线程池,用于响应客户端请求,因此在自己创建的Server端一定要主要合理使用synchronized和volatile关键词,以避免Binder线程并发导致产生脏数据问题,诱发不稳定复现的异常。