如何让异步监听器阻塞?

时间:2012-01-23 17:14:38

标签: java blackberry java-me bluetooth iobluetooth

我正在编写一个黑莓应用,它使用基于文本的AT命令与简单的蓝牙外设进行通信 - 类似于调制解调器...我只能使用事件监听器在黑莓上工作。所以通信现在是异步的。

但是,由于它是一个简单的设备,我需要控制并发访问,我宁愿只有一个阻塞调用。

我有以下代码尝试使用wait / notify将通信转换为阻塞。但是当我运行它时,notifyResults永远不会运行,直到getStringValue完成。即无论延迟何时,它总是会超时。

btCon对象已在单独的线程上运行。

我确信我错过了一些明显的线程。有人可以指出它吗?

由于

我还应该添加一个带有IllegalMonitorStateException的notifyAll。

我之前尝试过一个简单的布尔标志和一个等待循环。但是存在同样的问题。在getStringValue完成之后,notifyResult永远不会运行。

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
        }
    }

}

3 个答案:

答案 0 :(得分:2)

由于notifyResults和getStringValue都在同一个对象上有同步子句,假设getStringValues到达synchronized部分,notifyResults将在synchronized子句的开头阻塞,直到getStringValues退出同步区域。如果我理解,这就是你所看到的行为。

尼古拉斯的建议可能不错,但您可能在使用的BlackBerry API中找不到任何这些实现​​。您可能需要查看produce-consumer模式。

答案 1 :(得分:0)

根据Latch的建议,使用SemaphoreBarrierBrian Goetz book Java Concurrency in Practice可能更为合适。

这些类可以更轻松地编写阻止方法,并可能有助于防止错误,尤其是在您不熟悉wait()notifyAll()时。 (我不是说不熟悉,这只是其他人的注释......)

答案 2 :(得分:0)

代码可以正常工作。如果您将使用final对象而不是string变量。我很惊讶您没有获得NPE或IMSE。

创建字段:

private final Object resultLock = new Object();

更改所有已同步的部分以使用它而不是字符串字段result

我不喜欢魔法数字5秒。我希望您在应用程序中将null结果视为超时。