并发编程线程通信之管道流

前言

在并发编程中,需要处理两个问题:线程之间如何通信及线程之间如何同步。通知是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递

在共享内存的并发模型里,线程之间共享程序的公共状态,通过写-读内存中的公共状态进行隐式通信。而子啊消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过发送消息来显式进行通信。

Java 的并发才作用的是共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。

而Java中还有另一种用的比较少的线程间的通信方式:管道流。

如何使用?

管道输入/输入流和普通的文件输入/输出流或者网络输入/输出流不同之处在于,它主要用于线程之间的数据传输,而传输的媒介为内存。

管道输入/输入流主要包括了如下4种具体实现:PipedOutputStream,PipedInputStream,PipedReader 和 PipedWriter,前两种面向字节,而后两种面向字符。

我们先来一个例子看看:

public class PipedStreamDemo {
public static void main(String[] args) throws IOException {
PipedWriter writer = new PipedWriter();
PipedReader reader = new PipedReader();
PipedInputStream inputStream = new PipedInputStream();
PipedOutputStream outputStream = new PipedOutputStream();
// 将输出流和输入流连接
writer.connect(reader);
Thread printThread = new Thread(new Print(reader));
printThread.start();
int receive;
try {
while ((receive = System.in.read()) != -1) {
// 从main线程写到 print 线程
writer.write(receive);
}
} finally {
writer.close();
}
}
static class Print implements Runnable {
private PipedReader in;
public Print(PipedReader in) {
this.in = in;
}
@Override
public void run() {
int receive;
try {
while ((receive = in.read()) != -1) {
// 读取 main 线程发送过来的数据并打印
System.out.print((char) receive);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

上面的代码种,创建了 printThread,它用来接受 main 线程的输入,任何 main 线程的输入均通过 PipedWriter 写入,而 printThread 在另一端通过 PipedReader 将内容读出并打印。

对于 Piped 类型的流,必须先要进行绑定,也就是调用 connect 方法,如果没有将输入 / 输出流绑定起来,对于该流的访问将会抛出异常。

而作为这两个类连接的重要方法 connect 方法式如何实现的呢?

public synchronized void connect(PipedReader snk) throws IOException {
if (snk == null) {
throw new NullPointerException();
} else if (sink != null || snk.connected) {
throw new IOException("Already connected");
} else if (snk.closedByReader || closed) {
throw new IOException("Pipe closed");
}
sink = snk;
snk.in = -1;
snk.out = 0;
snk.connected = true;
}

首先参数判断,然后将输入流设置为输出流的 sink 属性。这样就将两个流关联了起来。实现了两个线程的通信。

总结

总的来说,该类的应用场景并不是很多,只是我们应该知道另一种线程通信的方式。嗯,就酱。

good luck !!!!

posted @   莫那-鲁道  阅读(228)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示