Lan*_*nek 7 java null multithreading android
我的程序在另一天尝试使用在另一个线程上创建的Handler向该线程发送消息时抛出了NullPointerException.尽管调用线程已经在另一个线程上调用了start,但是其他线程创建的Handler尚未创建,或者尚未对调用线程可见.这种情况很少发生.几乎每次测试都没有得到例外.
我想知道什么是最好的方法来避免这个问题,确保最小的复杂性和性能损失.该程序是一款游戏,性能非常敏感,特别是一旦运行.因此,我尝试避免在设置后使用同步,例如,并且宁愿在任何时候避免旋转变量.
背景:
在Android中,Handler类可用于"在不同于您自己的线程上执行操作".这里的文档:http:
//developer.android.com/intl/de/reference/android/os/Handler.html
必须在将使用它的线程上创建处理程序.因此,在线程的构造函数中创建它,由创建该线程的线程运行,不是一个选项.
当Handler用于UI线程以外的线程时,还必须使用Looper类: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();
}
}
Run Code Online (Sandbox Code Playgroud)
我非常丑陋的解决方案目前看起来像这样:
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.
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用创建线程中的代码如下所示:
LooperThread otherThread = new LooperThread();
otherThread.start();
otherThread.waitForSetupComplete();
otherThread.mHandler.sendEmptyMessage(0);
Run Code Online (Sandbox Code Playgroud)
还有更好的解决方案吗?谢谢.
And*_*min 12
我会选择经典的等待/通知
public class LooperThread extends Thread {
private Handler mHandler;
public void run() {
Looper.prepare();
synchronized (this) {
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
notifyAll();
}
Looper.loop();
}
public synchronized Handler getHandler() {
while (mHandler == null) {
try {
wait();
} catch (InterruptedException e) {
//Ignore and try again.
}
}
return mHandler;
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以多次使用从getHandler返回的处理程序而无需调用同步的getHandler.
准备一段时间的Looper阻止,所以我想你正在达到prepare()需要片刻才能完成的条件,因此mHandler仍未定义.
您可以Thread延长HandlerThread,但即使这样,您仍需要等待以确保Looper已初始化.也许这样的东西可能有用,你可以Handler单独定义,但是使用Looper自定义线程.
也许.
private void setUp() {
mHandlerThread = new CustomThread("foo", Process.THREAD_PRIORITY_BACKGROUND);
mHandlerThread.start();
// Create our handler; this will block until looper is initialised
mHandler = new CustomHandler(mHandlerThread.getLooper());
// mHandler is now ready to use
}
private class CustomThread extends HandlerThread {
public void run() {
// ...
}
}
private class CustomHandler extends Handler {
CustomHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3661 次 |
| 最近记录: |