0

わかりました、これは私が尋ねる必要がないと思った質問ですが、それは長い時間か何かのどちらかですが、私の心はぼやけているのでここに行きます.

HandlerThread、Looper、および Handler を使用したクラスの作成:

public class MyClass {
    //private volatile boolean mRunning   = false;
    private boolean mRunning              = false;
    private HandlerThread mHandlerThread  = null;
    private Handler mMessageHandler       = null;

    public static final int MESSAGE_START = 1;
    public static final int MESSAGE_STOP  = 2;

    public MyClass() {
        mHandlerThread = new HandlerThread("com.test.myclass");
        mHandlerThread.start();
        mMessageHandler = new MessageHandler(mHandlerThread.getLooper());
    }

    private class MessageHandler extends Handler {
        public MessageHandler(Looper looper) {
            super(looper);
        }

        private void start() {
            mRunning = true;
        }

        private void stop() {
            mRunning = false;
        }

        @Override
        public void handleMessage(final Message msg) {
            try {
                switch (msg.what) {
                    case MESSAGE_START:
                        start();
                        break;

                    case MESSAGE_STOP:
                        stop();
                        break;

                    default:
                        throw new RuntimeException("Invalid message: " + msg.what);
                }
            } catch (RuntimeException e) {
                stop();
            }
        }
    }

    public void release() {
        if (isRunning()) {
            stop();
        }

        // PS: is this a good way to stop HandlerThead/Looper in API =< 17 ?
        if (mHandlerThread != null) {
            mHandlerThread.quit();
            mHandlerThread = null;
        }
    }

    // Should this be a synchronized method
    public boolean isRunning() {
        return mRunning;
        /**
         * Or should the variable be synchronized itself?
         * synchronized(mRunning) { return mRunning; }
         */

        // Or just use a semaphore?
    }

    public void start() {
        mMessageHandler.sendEmptyMessage(MESSAGE_START);
    }

    public void stop() {
        mMessageHandler.sendEmptyMessage(MESSAGE_STOP);
    }
}

したがってmRunning、両方のスレッド (メインとルーパー) からアクセスされます。そのため、アクセスを同期する必要があります。あなたならどちらを選びますか?変数を揮発性にし (両方のスレッドが最新のローカル値を持つように)、isRunningメソッドを同期させますか? または経由で変数にアクセスしますsynchronized(mRunning){...}か?

最後に、releaseメソッドの実装、それは標準ごとですか? または、他の方法を選択しますか?

4

1 に答える 1

1

ロックの競合が少ない場合、ロックでの同期のコストは揮発性アクセスとほぼ同じです。競合が高い場合は、揮発性バージョンのパフォーマンスが向上する可能性があります。

ただし、これはできません。

synchronized(mRunning) { ... }  //ERROR!

mRunning はブール式です。ブール値で同期することはできません。オブジェクトでのみ同期できます。

于 2015-02-09T23:31:12.263 に答える