当前位置: 首页 > 知识库问答 >
问题:

BufferedReader readLine()阻塞,直到缓冲区满为止

田德馨
2023-03-14

我已经在网上搜索了几天这种现象,我可以找到一个类似问题的片段,这表明可能与底层的InputStreamReader和/或StreamDecoder有关,但这开始超出了我的专业知识。(见本链接)

所以我的问题是,我是否正确地实现了BufferedReader,以及如何解决我所看到的问题,以便在没有不必要的延迟的情况下获得每一行。

package serverTest;

import java.util.concurrent.BlockingQueue;

public class ServerTest {

    public static void main(String[] args) {

        int port = 54321;
        ServerSocketComms server = new ServerSocketComms(port);
        BlockingQueue<String> queue = server.getQueue();
        new Thread(server).start();
        
        ClientSocketComms client = new ClientSocketComms("localhost", port);
        new Thread(client).start();
        
        for(int i = 0; i < 1000; i++) { // should give about 10 seconds of output
            try {
                queue.put("" + i + " - All work and no play makes Jack a dull boy");
                // Slow things down enough to show what's happening
                Thread.sleep(10);
                // 48 characters should fill the 8K buffer in approximately 2 seconds
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
package serverTest;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class ServerSocketComms implements Runnable {

    private final BlockingQueue<String> queue = new LinkedBlockingQueue<>();
    private final int port;
    
    public ServerSocketComms(int port) {
        this.port = port;
    }
    
    @Override
    public void run() {
        // Open server socket and wait for connection
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            Socket socket = serverSocket.accept();

            // Continually loop over blocking data queue until stopped
            BufferedWriter dataOut = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            while(socket.isConnected()) {
                dataOut.write(queue.take());
                dataOut.newLine(); // delimit strings with a line separator
            }
            
            // Loop never exits because client socket never completes because of BufferedReader issue
            // so sockets never close and application never terminates
            socket.close();
            serverSocket.close();
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    public BlockingQueue<String> getQueue() {
        // Return a reference to the sending queue to be populated by other threads
        return this.queue;
    }
}
package serverTest;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class ClientSocketComms implements Runnable {

    private final String server;
    private final int port;
    
    public ClientSocketComms(String server, int port) {
        this.server = server;
        this.port = port;
    }
    
    @Override
    public void run() {
        // Open socket to server and wait for incoming data
        try {
            Socket socket = new Socket(server, port);
            BufferedReader dataIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));

            // Continually loop over incoming data until stopped
            String data;
            while((data = dataIn.readLine()) != null) {
                // Should print out every line as it's received,
                // but instead waits until buffer is full
                // (outputs about 170 lines at a time)
                System.out.println(data);
            }
            
            // Close socket and thread will die
            // (but loop never ends because buffer doesn't get completely refilled)
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

共有1个答案

拓拔阎宝
2023-03-14

您的服务器正在使用BufferedWriter:

BufferedWriter dataOut = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

这一个做你不喜欢的缓冲。默认的缓冲区大小似乎是您所看到的8K,尽管API中没有记录,而且可能会改变。如果在某个时间点希望确保缓冲区中存储的所有内容都立即发送给客户机,请尝试使用dataout.flush()刷新缓冲区。有关详细信息,请查看BufferedWriter API。

顺便说一句,我没有检查你的代码中是否有任何其他问题。但以上肯定是一个。

 类似资料:
  • 问题内容: 我正在寻找一种方法来阻止直到a 为空。 我知道,在多线程环境中,只要有生产者将项目放入,就可能会出现队列变空并且几秒钟后队列中充满项目的情况。 但是,如果只有 一个 生产者,则它可能要等待(并阻止)直到队列停止为空后再将其放入队列。 Java /伪代码: 你有什么主意吗? 编辑 :我知道包装和使用额外的条件可以解决问题,我只是问是否有一些预制的解决方案和/或更好的选择。 问题答案: 使

  • 问题内容: 在编写用于OpenGL库的Matrix类时,我遇到了一个问题,即使用Java数组还是使用Buffer策略存储数据(JOGL为Matrix操作提供直接缓冲区复制)。为了对此进行分析,我编写了一个小型性能测试程序,该程序比较了Arrays vs Buffers和Direct Buffers上循环和批量操作的相对速度。 我想在这里与您分享我的结果(因为我发现它们很有趣)。请随时发表评论和/或

  • 我刚刚开始学习vert. x,对它是如何工作的仍然感兴趣...我在想: 当反应性非阻塞垂直线卸载到阻塞垂直线时,阻塞垂直线在工作线程上运行。 1.what事件循环线程,关闭加载的工作,在同一时间?从循环中获取另一个事件? 返回a结果时,同一事件循环是否继续执行?还是另一个? 1的答案是什么 我觉得我错过了一些基本的东西,关于事情实际上是如何工作的。谢谢你的帮助!

  • 在循环队列的数组实现中,如果在第一个元素之前指向一个插槽,而在最后一个元素之后指向一个插槽,则会面临如何识别队列是满还是空的问题。 为了解决这个问题,我们要么使用计数器,要么在缓冲区中浪费一个空间。 我在想下面的方法。请纠正我的错误,如果没有请让我知道这是一个更好/更差的解决方案比以上。 null

  • 问题内容: 这是我要弄清楚的一个片段: 有一个接受来自外部的事件。有一个订阅该主题的客户端,可以处理事件并对其进行处理。这里的主要思想是,应基于使用流中的项目计算出的某些条件,每次都发出缓冲的项目。 为此,缓冲区边界本身会监听主体。 一项重要的期望行为:每当边界发射该项目时,也应将其包括在以下的发射中。当前配置不是这种情况,因为该项目(至少是我认为的)是 在 它到达 之前 从关闭选择器发出的,因此

  • 问题内容: 我有一个缓冲的,我一直用随机字符串填充它,直到time.Duration过去或直到它变满为止。 我的问题是,考虑到它是一次性任务,还是应该采用更便捷的方式,我是否应该为此使用股票报价器? 这是我目前的做法 问题答案: 我不是Go方面的专家(实际上,我从未使用过它),但是文档建议或仅针对单个事件。