阻止BufferedReader直到数据出现

时间:2013-10-14 03:32:14

标签: java multithreading sockets concurrency bufferedreader

我不确定如果我的描述正确,但这里有解释。

我有一个客户端消息处理系统,看起来很像这样:(它在一个单独的线程中运行)

public void run() {
    String line;

    while(true)
    {
        try
        {
            while ((line = reader.readLine( )) == null) { Thread.sleep(10); }; 

            if (line.toUpperCase().startsWith("PING ")) {
                // Autorespond to server pings
                server.Write("PONG " + line.substring(5));
            }
            else {
                setChanged();
                notifyObservers(line);
            }
        }
        catch (Exception e)
        {
            //do something here
        }
    }

}

我真的,真的,想要做的是,用其他东西替换这一行:while ((line = reader.readLine( )) == null) { Thread.sleep(10); },其他任何东西,这不是一个本质上无限循环。

代码细分 永远循环直到行包含一些数据。如果是ping请求,则自动响应并重新开始。如果不是,请通过收到的消息通知观察者,然后重新开始。

观察者模型有效,并不担心。读者确实可以正常工作......但它消耗了很多处理器,它们处于无限循环中,检查事物。

问题 我如何使用某种并发,等待或任何模型,以便线程本身只是等到BufferedReader实际上有数据要读取?有没有办法做到这一点,或者是Thread.Sleep(10)我实际上添加了最好的方法来避免无限制地吃掉我所有的处理器。

2 个答案:

答案 0 :(得分:4)

  

我真的,真的,想要做的是替换这一行:while((line = reader.readLine())== null){Thread.sleep(10);用其他东西,其他东西,这不是一个本质上无限的循环。

你在这里有一个基本的误解。在显示数据之前,readLine() 阻止。当您到达流末尾时,它只返回null,即文件结束或对等方已关闭连接。你不需要睡觉;你只需要将测试反转到!= null并将处理数据的代码放在循环中。

目前你正在 流的循环中旋转,这将永远不会终止。

答案 1 :(得分:-1)

如果reader与套接字/(未知长度流)相关联,那么就没有行尾,因此没有返回null。你知道这里最重要的是协议,客户端和服务器都应该知道数据的发送和接收方式,例如,HTTP协议头大小未知,所以服务器和客户端都需要空行( \r\n)女巫表示标题的结尾。 所以首先你需要拥有自己的协议,然后要注意空值。

public void run() {
    String line;

    while(true)
    {
        try
        {
            while (true) {
            line = reader.readLine( );//it throws exception if client/server closes the stream.
            if(line==null){return;/*break;*/}
            if (line.toUpperCase().startsWith("PING ")) {
                // Autorespond to server pings
                server.Write("PONG " + line.substring(5));
            }
            else {
                setChanged();
                notifyObservers(line);
            }
        }
        catch (Exception e)
        {
            //do something here
        }
      }
    }

}

也不需要Thread.sleep(),因为I / O操作会阻塞,直到某些数据可用,即使是2年也是如此。