2010-03-01 50 views
0

這個問題可能很長,但我想提供很多信息。J2ME/Java:通過線程引用StringBuffer

概述:我正在爲Blackberry創建一個股票行情代碼應用程序。但是我的StringBuffer存在一些問題,其中包含一個單獨的庫存信息。

過程:我的應用程序連接到SocketConnection處通過我們的服務器。服務器發送一組格式化的包含最新股票交易的字符串。因此,無論何時發生新的交易,服務器都會發送該交易的個別股票報價。通過InputStream,我可以讀取這些信息,並將每個字符放在一個由Threads引用的StringBuffer中。通過解析基於char3我能夠確定一組股票報價/信息。

CHAR1 - 到單獨的數據 CHAR3 - 裝置,股票報價/信息

樣品股票報價格式通過我們的服務器發送出去的端: stock_quote_name(CHAR 1)some_data(CHAR1)some_data(CHAR1) (CHAR3)

我的應用程序,然後分析該股票報價比較某些數據和格式它是如何看時顯示在屏幕上等等。當交易逐漸發生(緩慢)時,應用程序完美運行。然而..

問題:當交易在同一時間迅速,幾乎發生過,我的應用程序不能有效地處理髮送的信息。 StringBuffer將其內容與下一個交易結合在一起。含義兩個股票信息在一個StringBuffer中。

場應該是: Stock_quote_name some_data some_data發生了什麼事的

樣本: Stock_quote_name some_data some_dataStock_quote_name some_data some_data

這裏是我對於這部分代碼:

while (-1 != (data = is.read())) 
       { 
         sb.append((char)data); 
         while(3 != (data = is.read())) 
         { 
          sb.append((char)data); 
         } 
         UiApplication.getUiApplication().invokeLater(new Runnable() 
         { 
          public void run() 
          { 
           try 
           { 
            synchronized(UiApplication.getEventLock()) 
            { 
             SetStringBuffer(sb); 
             DisplayStringBuffer(); 
             RefreshStringBuffer(); 
            } 
           } catch (Exception e) 
           { 
            System.out.println("Error in setting stringbuffer: " + e.toString()); 
           } 
          } 
         }); 
       } 

public synchronized void DisplayStringBuffer() 
{ 
    try 
    { 
     //parse sb - string buffer 
     ...... 
    } 
    catch(Exception ex) 
    { 
     System.out.println("error in DisplayStringBuffer(): " + ex.toString()); 
    } 
} 
public synchronized void SetStringBuffer(StringBuffer dataBuffer) 
{ 
    this.sb =dataBuffer; 
    System.out.println(sb); 
} 
public synchronized void RefreshStringBuffer() 
{ 
    this.sb.delete(0, this.sb.length()); 
} 

從我可以看到,當交易發生得非常快時,StringBuffer不會立即刷新並仍然有c以前的交易的內容,當我嘗試提供新的數據。

我的問題是: 你們是否對我怎麼可以把數據放到StringBuffer的任何建議,而下一個信息被附加到第一個內容

回答

0

,你讀出的數據是同步的一部分,但是將數據附加到緩衝區的部分不是。如果您每次都重複使用相同的StringBuffer,則會出現競爭條件。

+0

那麼你是否建議我在每次While循環迭代時創建一個新的StringBuffer? – 2010-03-01 06:25:36

0

好吧,既然你正在使用的invokeLater設置/顯示/清除StringBuffer的,你說得對,沒有什麼東西會回升到一個read()調用和修改的StringBuffer阻止你,你能之前顯示它。

很明顯,你不是從事件線程的輸入流中讀取數據,所以爲了更新UI,你需要使用invokeLater或者在事件鎖定上同步,但是你同時執行這兩個操作。

如果你想使用invokeLater,那麼當你的事件線程嘗試在UI中顯示數據時,你需要確保你沒有用你的輸入流讀取器線程追加到你的StringBuffer。因此,您可能會考慮爲每個Runnable創建一個新的StringBuffer。

如果你想在事件鎖定上同步,類似這樣的東西可以工作(這可能會更好,因爲它避免了創建新的Runnables/StringBuffers不必要的垃圾創建)。

while (-1 != (data = is.read())) 
      { 
        sb.append((char)data); 
        while(3 != (data = is.read())) 
        { 
         sb.append((char)data); 
        } 

        synchronized(UiApplication.getEventLock()) 
        { 
         SetStringBuffer(sb); 
         DisplayStringBuffer(); 
         RefreshStringBuffer(); 
        } 
      } 
0

,因爲你正在閱讀的未來股票報價之前,UI線程完成顯示最後一個你無法重複使用同一個StringBuffer的每一個股票報價。請記住,您正在一個線程上寫入StringBuffer,並在另一個線程上讀取StringBuffer。不能保證在循環迭代之前UI線程(讀線程)已經調用了RefreshStringBuffer(),並開始將下一個股票報價附加到StringBuffer。

改爲使用字符串的集合。

java.util.queue<String> q = new java.util.concurrent.ConcurrentLinkedQueue<String>(); 

然後做q.add(sb.toString());當你完成把報價爲某人。

從您的UI線程,而不是

SetStringBuffer(sb); 
DisplayStringBuffer(); 
RefreshStringBuffer(); 

顯示報價,

public void DisplayStockQuote() { 
    while(!q.isEmpty()) { 
     String s = q.poll(); 

     // display s 
     try 
     { 
      //parse s - string containing stock quote 
      ...... 
     } 
     catch(Exception ex) 
     { 
      System.out.println("error in DisplayStringBuffer(): " + ex.toString()); 
     } 

    } 
} 

調用該方法,我建議你儘量避免額外的線程,並與布拉德利的解決方案去。但是,如果你真的想要兩個線程,這樣的事情會起作用。