2011-10-06 52 views
6

我正在執行一項Android服務,該服務將內容提供給其他可以註冊爲回調的應用程序。確保我的代碼是線程安全的

我不是100%確定Android Handler類是如何工作的,所以有人可以確認我的代碼是線程安全的嗎?

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); 
     } 
    }; 
} 

特別是,如果有人在處理程序處於for循環時調用unregisterCallback(),它會崩潰嗎?

從我的理解來看,Handler運行在同一個線程中,所以它是線程安全的,但我不確定。

感謝

+2

應該在:http://codereview.stackexchange.com/ –

回答

5

Handlers是線程安全的,這是他們的全部目的。
我會同意關於處理程序的線程安全性的文檔不是最好的,但如果設計爲在線程之間進行通信的類不是線程安全的,那將是非常具有諷刺意味的。

關於遠程回調,它們也被設計爲線程安全的,你應該閱讀本the documentation,它明確規定:

執行接口的基礎列表的鎖定來處理多線程的來電,並一個線程安全的方式迭代列表的快照,而不保持其鎖定

所有你必須確保所有變量多線程訪問是線程安全的(他們在你的情況),他們aren不會改變(你的是最終的,所以不用擔心)

+0

謝謝。我還發現[beginBroadcast()](http://developer.android.com/reference/android/os/RemoteCallbackList.html#beginBroadcast())製作了一個列表的副本,所以沒關係。 – Jonas

+0

道具思考線程安全雖然,這是相當叢林,並開始早期總是很好:) –

相關問題