メッセージを処理するバックグラウンドにあるワーカースレッドがあります。このようなもの:
class Worker extends Thread {
public volatile Handler handler; // actually private, of course
public void run() {
Looper.prepare();
mHandler = new Handler() { // the Handler hooks up to the current Thread
public boolean handleMessage(Message msg) {
// ...
}
};
Looper.loop();
}
}
メインスレッド(UIスレッド、それは重要ではありません)から私は次のようなことをしたいと思います:
Worker worker = new Worker();
worker.start();
worker.handler.sendMessage(...);
問題は、これが私を美しい競合状態に設定することworker.handler
です。読み取り時に、ワーカースレッドがすでにこのフィールドに割り当てられていることを確認する方法はありません。
コンストラクターはメインスレッドで実行されるため、コンストラクターHandler
からを単純に作成することはできません。そのため、コンストラクターは間違ったスレッドに関連付けられます。Worker
Handler
これは珍しいシナリオのようには思えません。私はいくつかの回避策を思い付くことができますが、それらはすべて醜いです:
このようなもの:
class Worker extends Thread { public volatile Handler handler; // actually private, of course public void run() { Looper.prepare(); mHandler = new Handler() { // the Handler hooks up to the current Thread public boolean handleMessage(Message msg) { // ... } }; notifyAll(); // <- ADDED Looper.loop(); } }
そしてメインスレッドから:
Worker worker = new Worker(); worker.start(); worker.wait(); // <- ADDED worker.handler.sendMessage(...);
しかし、これも信頼できるものではありません。の
notifyAll()
前に発生した場合wait()
、私たちは決して起こされません!イニシャル
Message
をWorker
'sコンストラクターに渡し、run()
メソッドにポストさせます。アドホックソリューションは、複数のメッセージに対しては機能しません。または、すぐに送信したくない場合はすぐに送信します。handler
ビジー-フィールドがなくなるまで待機しますnull
。うん、最後の手段...
スレッドに代わってHandler
とを作成したいのですが、これは不可能のようです。これから最もエレガントな方法は何ですか?MessageQueue
Worker