我的程序在前一天尝试使用另一个线程上创建的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