2012-01-23 78 views
2

我正在寫一個黑莓應用程序,它使用基於AT命令的文本與一個簡單的藍牙外設進行通信 - 類似於一個調制解調器...我只能使用事件監聽程序在黑莓上工作。所以通信現在是異步的。如何使異步偵聽器阻止?

但是,由於它是一個簡單的設備,我需要控制併發訪問,所以我寧願只進行阻塞調用。

我有以下代碼試圖通過使用等待/通知將通信轉換爲阻塞。但是當我運行它時,notifyResults永遠不會運行,直到getStringValue完成。即無論延遲如何,它總是會超時。

btCon對象已經在單獨的線程上運行。

我敢肯定,我錯過了線程的一些明顯的東西。有人可以好好指出嗎?

感謝

我還要補充的了notifyAll的吹了一個拋出:IllegalMonitorStateException。

我以前用一個簡單的布爾標誌和一個等待循環來測試它。但同樣的問題存在。 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 
     } 
    } 

} 

回答

0

可能更適合使用LatchSemaphore,或Barrier,所推薦的Brian Goetz book Java Concurrency in Practice

這些類可以使編寫阻塞方法更容易,並且可能有助於防止錯誤,特別是如果您不熟悉wait()notifyAll()。 (我並不是說你陌生,它只是爲別人筆記...)

+0

我還應該添加notifyAll和IllegalMonitorStateException。我以前用一個簡單的布爾標誌和一個等待循環來試用它。但同樣的問題存在。 notifyResult從不運行,直到getStringValue完成後。 –

+0

對於這種情況,我嘗試使用布爾標誌和等待循環,並在該循環中使用Thread.sleep()。我不使用任何信號量。但不知道爲什麼你的解決方案無法正常工作。 – Rupak

2

由於兩個notifyResults和向GetStringValue都在同一對象上同步的條款,假設getStringValues到達同步段第一notifyResults會在synchronized子句的開始處阻塞,直到getStringValues退出同步區域。如果我明白,這就是你所看到的行爲。

Nicholas的建議可能很好,但是您可能在您使用的BlackBerry API中找不到任何這些實現​​。你可能想看看produce-consumer模式。

0

該代碼將正常工作。如果你將使用final對象而不是字符串變量。我很驚訝你沒有得到NPE或IMSE。

創建領域:

private final Object resultLock = new Object(); 

改變所有同步段用它代替串場result的。

我不喜歡幻數5秒。我希望你在你的應用程序中將null結果視爲超時。

相關問題