我的程序在前一天嘗試使用另一個線程上創建的Handler向該線程發送消息時拋出了NullPointerException異常。由另一個線程創建的處理程序尚未創建,或者對於調用線程尚不可見,儘管調用線程已經在另一個線程上調用了啓動。這種情況很少發生。幾乎每個測試運行都沒有得到例外。如何在調用它之前確保另一個線程的處理程序不爲空?
我想知道什麼最好的方法是避免這個問題,肯定會造成最小的併發症和性能損失。該程序是一款遊戲,對性能非常敏感,特別是在運行時。因此,我嘗試避免在安裝後使用同步,例如,並且寧願隨時避免在變量上旋轉。
背景:
在Android中,Handler類可能被用來「排隊要在不同於你自己的線程上執行的動作」。這裏的文檔:
http://developer.android.com/intl/de/reference/android/os/Handler.html
處理程序必須在它將被使用的線程上創建。因此,在創建該線程的線程運行的線程的構造函數中創建它不是一個選項。
當處理程序是用於除UI線程以外的線程,套口類還必須使用:
http://developer.android.com/intl/de/reference/android/os/Looper.html
的文檔提供了使用兩個類用於此目的的該示例:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
我很醜陋的解決方法目前看起來是這樣的:
public class LooperThread extends Thread {
public volatile Handler mHandler;
public final ArrayBlockingQueue<Object> setupComplete = new ArrayBlockingQueue<Object>(1);
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
setupComplete();
Looper.loop();
}
public void waitForSetupComplete() {
while (true) {
try {
setupComplete.take();
return;
} catch (InterruptedException e) {
//Ignore and try again.
}
}
}
private void setupComplete() {
while(true) {
try {
setupComplete.put(new Object());
return;
} catch (InterruptedException e) {
//Ignore and try again.
}
}
}
}
隨着鱈魚e在創建線程看起來像這樣:
LooperThread otherThread = new LooperThread();
otherThread.start();
otherThread.waitForSetupComplete();
otherThread.mHandler.sendEmptyMessage(0);
有沒有更好的解決方案?謝謝。
啊,很好。 HandlerThread#getLooper可以完成阻塞,而不必處理額外的複雜性。對於我的特定應用程序,我甚至不需要子類HandlerThread。 – 2010-02-03 18:48:21