2011-10-06 24 views
6

Tôi đang làm một dịch vụ Android cung cấp nội dung cho các ứng dụng khác có thể đăng ký dưới dạng gọi lại.Đảm bảo rằng mã của tôi là an toàn chủ đề

Tôi không chắc chắn 100% về cách hoạt động của lớp Trình xử lý Android, vì vậy ai đó có thể xác nhận rằng mã này là chuỗi an toàn?

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

Cụ thể, nếu người nào đó gọi unregisterCallback() trong khi Trình xử lý đang trong vòng lặp, nó có bị lỗi không?

Từ hiểu biết của tôi, Trình xử lý chạy trong cùng một chuỗi, vì vậy nó là luồng an toàn, nhưng tôi không chắc chắn.

Cảm ơn

+2

Nên bật: http://codereview.stackexchange.com/ –

Trả lời

5

Handlers là chủ đề an toàn, đó là toàn bộ mục đích của chúng.
Tôi đồng ý rằng tài liệu về an toàn luồng của trình xử lý không phải là tốt nhất nhưng sẽ rất mỉa mai nếu một lớp được thiết kế để giao tiếp giữa chuỗi không phải là chủ đề an toàn.

Về callbacks từ xa, họ cũng được thiết kế để được đề an toàn, bạn nên đọc the documentation về vấn đề này, nó nêu rõ:

Thực hiện khóa của danh sách cơ bản của giao diện để đối phó với các cuộc gọi đến đa luồng, và một cách an toàn theo chủ đề để lặp qua một ảnh chụp nhanh của danh sách mà không cần giữ khóa của nó

Tất cả các biến là truy cập nhiều luồng là an toàn chủ đề (chúng nằm trong trường hợp của bạn) và chúng không được thay đổi (của bạn là cuối cùng vì vậy không phải lo lắng ở đó)

+0

Cảm ơn. Tôi cũng phát hiện ra rằng [beginBroadcast()] (http://developer.android.com/reference/android/os/RemoteCallbackList.html#beginBroadcast()) tạo một bản sao của danh sách, do đó, nó là tốt. – Jonas

+0

Đạo cụ suy nghĩ về an toàn luồng mặc dù, nó khá rừng và bắt đầu sớm luôn luôn là tốt :) –

Các vấn đề liên quan