2011-10-06 19 views
6

que estoy haciendo un servicio de Android que da contenido a otras aplicaciones que se pueden registrar como devolución de llamada.Asegúrese de que mi código es seguro para subprocesos

No estoy 100% seguro acerca de cómo funciona la clase Handler Android, por lo que puede que alguien me confirmo que este código es seguro para subprocesos?

public class MyService extends Service { 
    private static final String MESSAGE = "message"; 

    private final RemoteCallbackList<IMyCallback> readerCallbacks = new RemoteCallbackList<IMyCallback>(); 

    private static final int REPORT_MSG = 1; 

    private Thread readerThread; 

    @Override 
    public void onCreate() { 

     readerThread = new Thread(readerRunnable); 
     readerThread.setDaemon(true); 
     readerThread.start(); 

    } 

    private Runnable readerRunnable = new Runnable() { 
     @Override 
     public void run() { 
      while (!Thread.interrupted()) { 

       // Blocking call 
       byte[] message = JniCommunicator.readMessage(); 

       if (message == null || message.length == 0) { 
        continue; 
       } 

       Bundle b = new Bundle(); 
       b.putByteArray(MESSAGE, message); 
       Message m = readHandler.obtainMessage(REPORT_MSG); 
       m.setData(b); 
       readHandler.sendMessage(m); 
      } 
     } 
    }; 

    private final Handler readHandler = new Handler() { 
     @Override 
     public void handleMessage(Message msg) { 

      switch (msg.what) { 
      case REPORT_MSG: 

       byte[] message = msg.getData().getByteArray(MESSAGE); 

       // Broadcast the new message to all clients 
       final int N = readerCallbacks.beginBroadcast(); 
       for (int i = 0; i < N; i++) { 
        try { 
         readerCallbacks.getBroadcastItem(i).newMessage(message); 
        } catch (RemoteException e) { 
         // The RemoteCallbackList will take care of removing 
         // the dead object for us. 
        } 
       } 
       readerCallbacks.finishBroadcast(); 

       break; 
      } 
     } 
    }; 

     @Override 
    public IBinder onBind(Intent intent) { 
     return mBinder; 
    } 

    private final IService.Stub mBinder = new IService.Stub() { 

     public void registerCallback(IMyCallback cb) { 
      if (cb != null) 
       readerCallbacks.register(cb); 
     } 

     public void unregisterCallback(IMyCallback cb) { 
      if (cb != null) 
       readerCallbacks.unregister(cb); 
     } 
    }; 
} 

En particular, si alguien llama unregisterCallback() mientras el controlador está en el bucle, va a chocar?

Desde mi entender, la carrera Handler en el mismo hilo, por lo que es seguro para subprocesos, pero no estoy seguro.

Gracias

+2

Debe estar en: http://codereview.stackexchange.com/ –

Respuesta

5

Handlers son hilo de seguridad, es decir la totalidad de su propósito.
que estará de acuerdo en que la documentación sobre la seguridad de los subprocesos de los manipuladores no es la mejor, pero sería muy irónico que una clase diseñada para la comunicación entre el hilo no se hilo de seguridad.

Acerca de las devoluciones de llamada remotos, sino que también están diseñados para ser seguro para subprocesos, debe leer the documentation en esto, se establece claramente:

Realiza bloqueo de la lista subyacente de interfaces para hacer frente a las llamadas entrantes multiproceso, y una forma segura de subprocesos para iterar sobre una instantánea de la lista sin mantener su bloqueo

Todo lo que tiene que asegurarse es que todas las variables de acceso a subprocesos múltiples son seguras para hilos (que son en su caso) y que aren no se cambia (el tuyo es definitivo, así que no te preocupes)

+0

Gracias. También descubrí que [beginBroadcast()] (http://developer.android.com/reference/android/os/RemoteCallbackList.html#beginBroadcast()) hace una copia de la lista, por lo que está bien. – Jonas

+0

Apoyos en pensar acerca de la seguridad de los hilos, es bastante jungla y comenzar temprano siempre es bueno :) –

Cuestiones relacionadas