2011-10-06 13 views
6

私は、コールバックとして登録できる他のアプリにコンテンツを提供するAndroidサービスを行っています。自分のコードがスレッドセーフであることを確認してください

Androidハンドラクラスの仕組みについて100%確信していないので、誰かがこのコードがスレッドセーフであることを私に確認できますか?特に

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()を呼び出した場合、それがクラッシュしますか?

私の理解から、ハンドラは同じスレッドで実行されるため、スレッドセーフですが、わかりません。

おかげ

+2

する必要があります:http://codereview.stackexchange.com/ –

答えて

5

Handlersはそれが彼らの全体の目的は、スレッドセーフです。
ハンドラのスレッドセーフに関するドキュメントは最高ではありませんが、スレッド間で通信するように設計されたクラスがスレッドセーフでない場合は非常に皮肉になります。マルチスレッドの着信コールに対処するためのインターフェースの根底にあるリストの

行うロックを、および:リモートコールバックについて

、彼らはまた、スレッドセーフであるように設計されている、あなたがこの上the documentationを読んでください、それは明確に述べてロックを保持せずにリストのスナップショットを反復処理するスレッドセーフな方法

すべての変数は、スレッドセーフであることが保証されています。変更されていない(最終的にあなたの心配もありません)

+0

ありがとうございます。また、[beginBroadcast()](http://developer.android.com/reference/android/os/RemoteCallbackList.html#beginBroadcast())がリストのコピーを作成していることも分かりました。 – Jonas

+0

スレッドの安全性を考える上で小道具、それはかなりジャングルだし、早く始めるのはいつもいいです:) –

関連する問題