java如何使异步侦听器执行阻塞?
我正在编写一个黑莓应用程序,它使用基于文本的AT命令与一个简单的蓝牙外围设备进行通信,类似于调制解调器。。。我只能使用事件侦听器在blackberry上运行它。因此,通信现在是异步的
然而,因为它是一个简单的设备,我需要控制并发访问,所以我更喜欢只进行阻塞调用
我有下面的代码,它试图通过使用wait/notify将通信转换为阻塞。但当我运行它时,notifyResults在getStringValue完成之前不会运行。i、 e.无论延迟如何,它都将始终超时
btCon对象已在单独的线程上运行
我确信我在线程方面遗漏了一些明显的东西。有人能指出吗
谢谢
我还应该添加notifyAll爆炸与非法监视器状态异常
我以前用一个简单的布尔标志和一个等待循环来尝试它。但同样的问题也存在。notifyResult在getStringValue完成之前不会运行
public class BTCommand implements ResultListener{
String cmd;
private BluetoothClient btCon;
private String result;
public BTCommand (String cmd){
this.cmd=cmd;
btCon = BluetoothClient.getInstance();
btCon.addListener(this);
System.out.println("[BTCL] BTCommand init");
}
public String getStringValue(){
result = "TIMEOUT";
btCon.sendCommand(cmd);
System.out.println("[BTCL] BTCommand getStringValue sent and waiting");
synchronized (result){
try {
result.wait(5000);
} catch (InterruptedException e) {
System.out.println("[BTCL] BTCommand getStringValue interrupted");
}
}//sync
System.out.println("[BTCL] BTCommand getStringValue result="+result);
return result;
}
public void notifyResults(String cmd) {
if(cmd.equalsIgnoreCase(this.cmd)){
synchronized(result){
result = btCon.getHash(cmd);
System.out.println("[BTCL] BTCommand resultReady: "+cmd+"="+result);
result.notifyAll();
}//sync
}
}
}
# 1 楼答案
代码将正常工作。如果要使用final对象而不是字符串变量。我很惊讶你没有得到NPE或IMSE
创建字段:
更改所有已同步的节以使用它而不是字符串字段
result
我不喜欢魔法数字5秒。我希望您在应用程序中将空结果视为超时
# 2 楼答案
由于notifyResults和getStringValue在同一对象上都有同步子句,因此假设getStringValues首先到达同步部分,notifyResults将在同步子句的开头阻塞,直到getStringValues退出同步区域。如果我理解的话,这就是你看到的行为
Nicholas的建议可能很好,但您可能在正在使用的BlackBerry API中找不到这些实现。您可能想看看produce-consumer模式
# 3 楼答案
按照Brian Goetz book Java Concurrency in Practice的建议,使用^{} 、^{} 或^{} 可能更合适
这些类将使编写阻塞方法变得更容易,并且可能有助于防止bug,特别是当您不熟悉
wait()
和notifyAll()
时。(我不是说你不熟悉,这只是给别人的一个提示…)