我在尝试在后台线程中调用主线程时遇到了一些问题。
根据这篇文章:Running code in main thread from another thread
解决方案应该是:
private void runOnMainThread() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// Do something
ottoBus.post(new MyObjectEvent(mMyObject));
// End do something
mMyObject = null;
}
});
}
然而,我的后台线程仍然能够在"做某事"之间读取蓝牙套接字数据。和#34;结束做某事"
我在这里缺少什么?是否可以锁定后台线程,同时"做某事"正在执行?
我的读取套接字数据的代码如下:
InputStream stream = null;
InputStreamReader reader = null;
BufferedReader bufferedReader = null;
String data = "";
try {
stream = mSocket.getInputStream();
byte[] bytes = new byte[20];
int numRead = 0;
while ((numRead = stream.read(bytes)) >= 0) {
String s = new String(bytes, 0, numRead);
if (mMyObject != null) {
fillData(s); // Can cause NPE
} else {
mMyObject = new MyObject();
fillData(s);
}
// This should be synchronised call
runOnMainThread();
感谢。
答案 0 :(得分:2)
您需要使用名为wait/notify的Java模式。简单地说:它定义了两个线程, 生产者和消费者,以便消费者在启动生产者之后停止并等待生产者线程完成。
它是这样的:
static final object uiActionMonitor = new Object();
transient boolean uiCompleted;
void network_thread_run() {
int numRead = 0;
while ((numRead = stream.read(bytes)) >= 0) {
String s = new String(bytes, 0, numRead);
// This should be synchronised call
uiCompleted = false;
runOnMainThread();
synchronized(uiActionMonitor) { //<---------- wait for UI to complete
while (!uiCompleted) {
uiActionMonitor.wait();
}
}
}
UI代码:
private void runOnMainThread() {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
// Do something
// End do something
uiCompleted = true;
synchronized(uiActionMonitor) { //<---------- release networking thread
uiActionMonitor.notifyAll();
}
}
});
}
完全按原样复制同步逻辑。这是许多开发人员弄错的地方。
我必须承认,当UI线程正在处理您的消息时,我无法理解为什么需要阻止您的网络线程......
答案 1 :(得分:0)
我认为你需要使用锁或同步集团。您可以查看java concurency documentation以及更具体的this和this部分。 通过这种方式,您可以保证代码的某些部分不会同时执行多个时间。
答案 2 :(得分:0)
我发现CountDownLatch
是完成此类事情的最简单方法。这是一个可重用的方法,用于在主线程上运行Runnable
并阻止它们完成:
private static final Handler mainHandler = new Handler(Looper.getMainLooper());
private static void runOnMainThreadBlocking(Runnable runnable) throws InterruptedException {
CountDownLatch completionSignal = new CountDownLatch(1);
mainHandler.post(new Runnable() {
@Override public void run() {
runnable.run();
completionSignal.countDown();
}
});
completionSignal.await();
}