Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • 计算机基础
  • 操作系统原理
  • Linux
  • MacOS
  • Windows
  • 系统工程与研究专题
  • AI 基础
  • 大模型基础
  • Prompt 工程
  • RAG 检索增强生成
  • Agent 智能体
  • AI 应用开发
  • AI 工程化
  • AI 安全与治理
  • AI 面试与设计题
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java章节编写规范
  • Java基础

  • Java集合

  • Java并发

  • Java IO

    • Java IO概述
    • IO基础

    • 常用IO流

      • 文件流
      • 缓冲流
      • 数据流
      • 对象流与序列化
      • 打印流
      • 管道流
        • 1. 核心类
        • 2. 字节管道示例
        • 3. 管道流的特点
        • 4. 和 BlockingQueue 的对比
        • 5. 使用注意点
        • 专家实践清单
        • Tips 快问快答
        • 6. 总结
    • 文件与目录操作

    • Java NIO

    • 高级主题

    • 实践与性能优化

    • 面试与设计题

    • IO实践速查

  • JVM

目录

管道流

管道流用于在线程之间传递数据。一个线程写入管道输出流,另一个线程从管道输入流读取。

# 1. 核心类

字节管道流:

  • PipedInputStream
  • PipedOutputStream

字符管道流:

  • PipedReader
  • PipedWriter

它们必须成对连接。

# 2. 字节管道示例

import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;

public class PipedStreamDemo {
    public static void main(String[] args) throws Exception {
        PipedInputStream input = new PipedInputStream();
        PipedOutputStream output = new PipedOutputStream(input);

        Thread producer = new Thread(() -> {
            try (output) {
                output.write("hello pipe".getBytes(StandardCharsets.UTF_8));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });

        Thread consumer = new Thread(() -> {
            try (input) {
                byte[] buffer = new byte[1024];
                int len = input.read(buffer);
                System.out.println(new String(buffer, 0, len, StandardCharsets.UTF_8));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });

        consumer.start();
        producer.start();
    }
}

# 3. 管道流的特点

管道流有几个关键特点:

  • 适合线程间一边生产、一边消费。
  • 内部缓冲区有限,写入过快而读取过慢会阻塞。
  • 如果读写双方没有正确启动,容易死锁。
  • 不适合复杂的多生产者、多消费者场景。

# 4. 和 BlockingQueue 的对比

实际业务中,线程间传递数据更常用 BlockingQueue。

对比项 管道流 BlockingQueue
数据形式 字节或字符流 任意对象
使用难度 较高 较低
背压能力 有限缓冲阻塞 队列容量控制
业务表达 偏底层 更直观
常见程度 较少 很常见

如果数据本身就是流式字节,管道流有价值。如果是业务对象,优先考虑队列。

# 5. 使用注意点

  • 不要在同一个线程中同时读写管道,容易阻塞。
  • 必须连接输入端和输出端。
  • 要正确关闭输出端,否则读取端可能一直等待。
  • 异常处理要能通知对端,否则另一端可能一直阻塞。

# 专家实践清单

检查项 要求 风险
线程模型 读写端放在不同线程 同线程读写容易死等
连接关系 输入端和输出端必须连接 未连接会抛异常
关闭协议 输出端完成后关闭 读取端可能一直等待
异常传递 一端失败要通知另一端 对端阻塞无法退出

管道流的协作模型:

生产线程
  │ PipedOutputStream
  ▼
管道缓冲区
  │ PipedInputStream
  ▼
消费线程

# Tips 快问快答

Q:管道流解决什么问题? A:在两个线程之间以流的方式传递数据。

Q:管道流能跨进程通信吗? A:不能,它是 JVM 内线程间通信工具。

Q:为什么不能在同一线程中同时读写? A:管道缓冲区满或空时会阻塞,单线程容易互相等待。

Q:管道流和 BlockingQueue 怎么选? A:传字节流可用管道流,传对象任务通常 BlockingQueue 更清晰。

Q:读取端什么时候知道结束? A:输出端关闭后,读取端最终读到 -1。

Q:管道缓冲区满了会怎样? A:写入端会阻塞,直到读取端消费数据。

Q:生产代码常用管道流吗? A:不多,更多使用队列、响应式流或消息中间件。

Q:管道流最重要的边界是什么? A:要设计关闭、异常通知和线程退出协议。

# 6. 总结

管道流是 Java IO 中用于线程间流式通信的工具,适合学习流式生产消费模型。生产业务中它出现频率不高,因为 BlockingQueue、响应式流、消息队列等方案通常更易维护。

上次更新: 2026/06/25, 14:19:18
打印流
File类

← 打印流 File类→

Copyright © 2023-2026 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式