android系统service组件的线程关系

时间:2022-11-01 18:18:43

                                               Android系统service组件的线程关系

        Service是Android系统提供的4大组件之一,我们在应用的开发过程中会经常通过AIDL的方式用到。但是当应用在使用该service服务时,服务提供的方法所运行在的线程却不是很清楚,本文通过一些代码实验给出初步的结论,不足处请更正:

         初步结论:

         1. 当服务是本地服务时(即服务和服务的使用者是一个进程),service服务组件提供的方法所运行在的线程 取决于 调用此方法的调用者所处的线程。 我们在教科书上获  得信息是:本地服务是运行在主线程中的,如果提供的方法太耗时,会产生ANR。此情况的前提是,访问此方法的调用者就是主线程,即一般TID为1的线程;如果我们在子线程中访问服务提供的方案,那么本地服务中的方法所运行在的线程就是调用此方法的线程。所以对于本地服务,服务提供的方法所运行在的线程,取决于调用者所在的线程。

        2. 当服务不是本地服务时(即服务和服务的使用者不是一个进程,有设置process属性),service服务组件提供的方法所运行在的线程 与 调用者无关,因为是跨进 程访问。那么在service服务所在进程中,service提供的方法被访问时,方法所运行在的线程不是service的主线程,而是子线程。此子线程是在service组件 被 新创建的进程加载前,系统为该进程创建的binder线程。

           代码比较简单,在如下 MainActivity  中调用服务提供的方法:

                  public class MainActivity extends Activity {
    
    
                                   public final String TAG = "MainActivity" ;
    
                                   private Iservicetest serviceTest = null;
    
                                   private static final HandlerThread sWorkerThread = new HandlerThread( "service-worker");
                                   static {
                                                 sWorkerThread.start();
                                             }
                                   private static final Handler sWorker = new Handler(sWorkerThread.getLooper());
                                   private static final Handler mWorker = new Handler(
                                   Looper.getMainLooper());
    
                                  @Override
                                  protected void onCreate(Bundle savedInstanceState) {
                                                   super.onCreate(savedInstanceState);
                                                   boolean retVal = false ;
                                                   setContentView(R.layout.activity_main);
        
                                                   Intent bindItent = new Intent(MainActivity.this,servicetest.class);
                                                   retVal = bindService(bindItent,serviceTestConnection,Context.BIND_AUTO_CREATE);
                
                                                   Log.d(TAG,"bindService="+retVal);
                                                   Log.d(TAG,"ThreadID="+Thread.currentThread().getId());
                                                  sWorker.postDelayed(new Runnable(){
                                                                @Override
                                                                 public void run() {                   
                                                                         try{      
                                                                          Log.d(TAG," sWorker ThreadID="+Thread.currentThread().getId());
                                                                          serviceTest.getVal(0);  
                                                                          serviceTest.setVal(0);   
                                                                          } catch (Exception e) {
                                                                         e.printStackTrace();
                                                                         return;
                                                                         }
                                                                }
                                                           },2000);
             
                                   mWorker.postDelayed(new Runnable(){
                                                                                 @Override
                                                               public void run() {                   
                                                                        try {
                                                                        Log.d(TAG," mWorker ThreadID="+Thread.currentThread().getId());
                                                                        serviceTest.getVal(0);  
                                                                        serviceTest.setVal(0);   

                                                                        } catch (Exception e) {
                                                                        e.printStackTrace();
                                                                        return;
                                                                        }
                                                                  }
                                                           },2000);
        
        
        
        }

    如下是示意的service服务的代码:

                private ServiceConnection serviceTestConnection = new  ServiceConnection() {
        
                                    public void onServiceConnected(ComponentName className ,IBinder service){
                                           Log.d(TAG,"servie onServiceConnected");
                                           serviceTest = Iservicetest.Stub.asInterface(service);
                                            Log.d(TAG," onServiceConnected ThreadID="+Thread.currentThread().getId());
                
                                    }
                                   public void onServiceDisconnected(ComponentName className){
                                           serviceTest = null;
                                           Log.d(TAG,"servie disconnected");
                                           Log.d(TAG," onServiceDisconnected ThreadID="+Thread.currentThread().getId());
                                    }
            
                   };
    


    public class servicetest extends Service {
                   public String TAG     = "servicetest" ;    
                   @Override
                   public void onCreate() {
                          super.onCreate();
                          Log.d(TAG," servicetest onCreate threadID="+Thread.currentThread().getId());
                   }    
                  @Override
                  public IBinder onBind(Intent intent) {
                   // TODO Auto-generated method stub
                   Log.d(TAG," servicetest onBind threadID="+Thread.currentThread().getId());
                   return stub;
                   }
    
    private Iservicetest.Stub stub = new Iservicetest.Stub() {
                   public int getVal(int addr ){
                   Log.d(TAG," getVal TID="+Thread.currentThread().getId());
                   return 0;
                  }
        
                  public int setVal(int val ){
                  Log.d(TAG,"setVal TID="+Thread.currentThread().getId());
                  return 0;
                  }
        
    };
}