0

这个问题可能很长,但我想提供很多信息。

概述:我正在为 Blackberry 创建一个 Stock Quotes Ticker 应用程序。但我的 StringBuffer 包含单个股票信息时遇到问题。

流程:我的应用程序通过 SocketConnection 连接到我们的服务器。服务器发出一组格式化的字符串,其中包含最新的股票交易。因此,每当发生新交易时,服务器都会发送该交易的单个股票报价。通过 InputStream,我能够读取该信息并将每个字符放在线程引用的 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 不会立即刷新,并且仍然具有上一笔交易的内容。

我的问题是: 你们对我如何将数据放入 StringBuffer 有任何建议,而无需将下一个信息附加到第一个内容

4

3 回答 3

0

The part where you read data is synchronized, but the part where you append data to the buffer is not. If you are reusing the same StringBuffer each time, you will have a race condition.

于 2010-03-01T05:08:05.887 回答
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();
                   } 
            }
于 2010-05-10T03:34:30.453 回答
0

您不能为每个股票报价重复使用相同的 StringBuffer,因为您在 UI 线程完成显示最后一个股票报价之前正在阅读下一个股票报价。请记住,您正在一个线程上写入 StringBuffer,并在另一个线程上读取 StringBuffer。无法保证 UI 线程(读取线程)在循环迭代并开始将下一个股票报价附加到 StringBuffer 之前调用了 RefreshStringBuffer()。

改为使用字符串集合。

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

然后q.add(sb.toString());在您完成将报价放入某人时执行此操作。

显示报价

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());
        }

    }
}

从您的 UI 线程调用该方法,而不是

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

我建议您尝试避免使用额外的线程并使用 Bradley 的解决方案。但是如果你真的想要有两个线程,这样的事情就可以了。

于 2010-05-10T04:39:14.567 回答