面试串讲014-实现了AIDL接口的服务的方法是运行在哪个线程?有多个方法,是不是运行在同一个线程?

55 阅读1分钟

问题:

实现了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完成");
 }

运行后日志输出如下:

mianshi014-1

可以看出addBook和getBookList方法分别运行在Binder:2374_4和Binder:2374_2这两个Binder线程中。

结合上述示例可以看出,在Binder通信机制中,Server端有一个Binder线程池,用于响应客户端请求,因此在自己创建的Server端一定要主要合理使用synchronized和volatile关键词,以避免Binder线程并发导致产生脏数据问题,诱发不稳定复现的异常。