You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下如何用Java/Kotlin实现命名管道的阻塞式数据监听

在Linux下用Kotlin/Java阻塞式监听命名管道

你的问题核心是:当前代码在命名管道无数据(或写端关闭)时,readLine()返回null导致循环空转占用CPU,需要实现有数据时读取、无数据时阻塞的效果。

问题原因

Linux命名管道的特性是:

  • 当管道有写端连接且无数据时,读操作会阻塞,直到有数据写入或写端关闭。
  • 当所有写端关闭时,读操作会立即返回EOF(对应Java/Kotlin中readLine()返回null)。

你的代码在遇到EOF后没有重新打开管道,而是持续调用readLine(),每次都返回null,导致循环空转。

解决方案

只需要在readLine()返回null时,重新打开管道即可。这样当新的写端连接管道时,读操作会再次进入阻塞状态,直到有数据写入。

Kotlin 实现代码

const val PIPE_NAME = "/tmp/my_named_pipe"

fun main() {
    while (true) {
        File(PIPE_NAME).bufferedReader().use { reader ->
            var line: String?
            do {
                line = reader.readLine()
                line?.let {
                    // 处理读取到的行数据
                    println("收到数据: $it")
                }
            } while (line != null)
            // 写端关闭后,自动关闭当前reader,循环重新打开管道等待新连接
        }
    }
}

Java 实现代码

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class PipeListener {
    private static final String PIPE_NAME = "/tmp/my_named_pipe";

    public static void main(String[] args) {
        while (true) {
            try (BufferedReader reader = new BufferedReader(new FileReader(PIPE_NAME))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    // 处理读取到的行数据
                    System.out.println("收到数据: " + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 写端关闭后,重新打开管道等待新连接
        }
    }
}

说明

  • 使用use块(Kotlin)或try-with-resources(Java)确保管道关闭后流资源能被正确释放。
  • 当写端关闭导致readLine()返回null时,退出当前读取块,循环重新打开管道,此时新的读操作会阻塞,直到有新的写端连接并写入数据。
  • 这种方式完全符合需求:有数据时立即读取,无数据时阻塞等待,不会产生CPU空转。

内容的提问来源于stack exchange,提问作者artem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 04:40:37