确保我的代码是线程安全的

时间:2011-10-06 16:40:53

标签: android handler android-service

我正在做一项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在同一个线程中运行,所以它是线程安全的,但我不确定。

由于

1 个答案:

答案 0 :(得分:5)

Handlers是线程安全的,这是他们的全部目的 我同意关于处理程序的线程安全性的文档不是最好的,但是如果设计用于线程之间通信的类不是线程安全的话,那将是非常具有讽刺意味的。

关于远程回调,它们也被设计为线程安全的,您应该阅读the documentation,它明确说明:

执行锁定底层接口列表以处理多线程传入调用,以及一种线程安全的方法来迭代列表的快照而不保持其锁定

所有你必须确保所有变量多线程访问是线程安全的(它们在你的情况下)并且它们没有被更改(你的是最终的所以不用担心那里)