javaIO——PipedReader & PipedWriter
1. 概述:
PipedReader 和 PipedWriter,意为管道读写流。所谓管道,那就是有进有出,所以这也是它们跟其它流对象最显著的区别:PipedReader和PipedWriter必须成对使用才有意义。
2. 角色扮演:
PipedWriter 扮演生产者的角色,将字符数据写入到管道;PipedReader扮演消费者的角色,负责将数据从管道取出消费掉。
3. 数据结构:
要实现一个管道,至少需要三个要素:一个线性存储结构、一个写入位置标记、一个读取位置标记。java中把这三个要素放在了PipedReader中:
从代码注释可以看出,buffer[] 就是存储数据的线性结构、in 是写入的位置标记、out是读取的位置标记。"The circular buffer" 说明buffer数组是循环使用,那么肯定会牵涉到数据覆盖的问题,后文中会讲到怎么解决。注释中还说:in<0 表示管道为空(没有数据),in==out 表示管道满了。
4. 构造:
4.1. PipedWriter有两个构造方法,一个无参构造方法,一个带有一个PipedReader对象的构造方法。使用前者时只是单单构造一个Writer对象,没有建立连接,需要后续手动调用connect方法建立连接才能write数据;使用后者时会在构造完成时调用connect方法建立管道连接:
4.2. PipedReader有4个构造方法,两个参数可选:需要建立连接的Writer对象和管道长度(默认1024):
可以看出,PipedWriter和PipedReader都提供了带有连接对象参数的构造函数,所以实际应用中,他们之间构造的先后顺序可以自己决定。
5. 建立连接:
PipedReader中保存着连接标志: boolean connected = false; PipedWriter中保存着对PipedReader的引用: private PipedReader sink; 两个类中都有 connect 方法,而其实 PipedReader 中的 conncet 方法最终也是通过调用 PipedWriter 中的 connect 方法,如下:
我们看到,连接方法做了以下几件事:
5.1. 异常检查,包括:为空检查、已连接检查、已关闭检查(通过同步机制,保证这些检查的结果是可信的);
5.2. 建立 PipedWriter 对 PipedReader 的引用;
5.3. 初始化管道位置标记;
5.4. 将连接标志置为 true;
6. 写入数据:
PipedWriter 有两个 write 方法,最终都是调用 PipedReader 的 receive 方法实现的(其实这很自然,因为 buffer 本身就是放在PipedReader中的),所以写入数据的核心方法是 synchronized void receive(int c) throws IOException :
从代码可以看出:
6.1. 写入方法是同步的。如果不同步,那么可能导致不同线程写入的数据相互覆盖;
6.2. 写入方法是阻塞的。当管道已满却要写入数据的时候,会首先唤醒监听当前对象锁的所有线程(当然也包括读取线程)让他们进入就绪态,准备竞争锁资源;然后让当前执行写入的线程放弃对象锁,沉睡1秒。这样一来,才有可能让该对象锁上的读取线程从管道读取数据,将管道腾出部分或者全部的空间,当前线程才能继续写入数据,结束阻塞状态。
7. 读取数据:
PipedReader有两个 read 方法,分别是读取单个字符和多个,大同小异,下面是读取单个字符的方法:
从代码可以看出:
7.1. read 方法是同步的。
7.2. read 方法是阻塞的。当管道已空却需要读取数据时,首先唤醒当前对象锁上的其它线程(包括写入线程);然后让当前执行读取的线程沉睡1秒,放弃锁资源,这样一来才有可能让该对象锁上的写入线程写入数据,当前线程才有数据可读,结束阻塞状态。
8. 写入结束和关闭管道:
可以从Writer或者Reader任意一方关闭管道, closeByReader 和 closeByWriter 会标记从哪一方关闭的,并且若是从 Writer 方关闭的,会调用 PipedReader 的 synchronized void receivedLast() 方法,从而唤醒所有线程。
9. 总结:
9.1. PipedReader 和 PipedWriter 需要成对使用,才能建立管道;
9.2. 管道是通过一个循环使用的字符数组实现的;
9.3. write 和 read 都是同步的;
9.4. write 和 read 都是阻塞的(write 时管道已满就阻塞,read时管道已空就阻塞);
10. 小小实践:
https://www.cnblogs.com/coding-one/p/11352217.html
javaIO——PipedReader & PipedWriter的更多相关文章
- javaIO——PipedReader 和 PipedWriter 实现模拟即时聊天
上一篇学习了javaIO里面的 PipedReader 和 PipedWriter,这里对两个类做一个小小的练习:实现一个即时消息发送和接收的聊天系统(这里只实现单向发送,双向同理,定义两个管道即可) ...
- Java 管道PipedInputStream PipedOutStream PipedReader PipedWriter
java中的管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据.一个线程发送数据到输出管道,另外一个线程从输入管道中读取数据.通过使用管道,实现不同线程间的通信,而不必借助类似 ...
- Java-IO之PipedReader和PipedWriter
PipedReader和PipedWriter与PipedInputStream和PipedOutputStream一样,都可以用于管道通信.PipedWriter是字符管道输出流,继承于Writer ...
- [十九]JavaIO之PipedReader 和 PipedWriter
功能简介 还记得PipedInputStream 和 PipedOutputStream么 我们之前是这么说的: p, li { white-space: pre-wrap; } 使用管道通信时,必 ...
- Java_io体系之PipedWriter、PipedReader简介、走进源码及示例——14
Java_io体系之PipedWriter.PipedReader简介.走进源码及示例——14 ——管道字符输出流.必须建立在管道输入流之上.所以先介绍管道字符输出流.可以先看示例或者总结.总结写的有 ...
- java io系列20之 PipedReader和PipedWriter
本章,我们学习PipedReader和PipedWriter.它们和“PipedInputStream和PipedOutputStream”一样,都可以用于管道通信. PipedWriter 是字符管 ...
- Java学习日记之 Java-IO流
Java中的IO流在处理上分为字节流和字符流.字节流和字符流的区别 : 1.字节流读取的时候,读到一个字节就返回一个字节: 字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在UTF-8 ...
- [三]JavaIO之IO体系类整体设计思路 流的概念以及四大基础分类
从本文开始,将正式进入JavaIO的简介 在继续javaIO系列的文章之前 可以过去看一下 本人博客上的设计模式中的 适配器模式和装饰器模式 这会对接下来的阅读大有帮助 本文是从逻辑上介绍整个的J ...
- [四] JavaIO之类层次体系结构横向比对
IO家族类层次体系结构横向匹配 上一篇文章中主要介绍了JavaIO流家族的整体设计思路,简单回顾下 基本逻辑涉及数据源 流的方向,以及流的数据形式这三个部分的组合 按照流的数据形式和流的方向, ...
随机推荐
- 记录学习Linux遇到的问题
shl@shl-tx:~$ ifconfig Command 'ifconfig' not found, but can be installed with: sudo apt install net ...
- 安装vue模板时,选择webpack-simple还是Webpack?
选用模板常用的是webpack与webpack-simple.webpack-simple是基于Webpack@2.1.0-beta.25进行配置的版本,而webpack模板则是基于Webpack ^ ...
- Facebook币Libra学习-6.发行属于自己的代币Token案例(含源码)
在这个简短的概述中,我们描述了我们在eToro标记化资产背后实施技术的初步经验,即MoveIR语言中的(eToken),用于在Libra网络上进行部署. Libra协议是一个确定性状态机,它将数据存储 ...
- dbtreeview
http://www.delphipages.com/comp/dynamic_dbtreeview-6302.html https://files.cnblogs.com/files/jijm123 ...
- [C++]哈夫曼树(最优满二叉树) / 哈夫曼编码(贪心算法)
一 哈夫曼树 1.1 基本概念 算法思想 贪心算法(以局部最优,谋求全局最优) 适用范围 1 [(约束)可行]:它必须满足问题的约束 2 [局部最优]它是当前步骤中所有可行选择中最佳的局部选择 3 [ ...
- 如何开始学习使用TensorFlow?
Harrison Kinsley ——PythonProgramming.net的创始人 TensorFlow官方网站有相当多的文档和教程,但这些往往认为读者掌握了一些机器学习和人工智能知识.除了知道 ...
- Android学习笔记之View
转载: 0.7562018.10.22 21:44:10字数 5,423阅读 189 导图 一.View事件体系 1.什么是 View 和 View的位置坐标 View是什么: View 是一种界 ...
- [Tensorflow] 使用 Mask_RCNN 完成目标检测与实例分割,同时输出每个区域的 Feature Map
Mask_RCNN-2.0 网页链接:https://github.com/matterport/Mask_RCNN/releases/tag/v2.0 Mask_RCNN-master(matter ...
- 《Java语言程序设计》
课堂测试:用户需求:英语的26 个字母的频率在一本小说中是如何分布的?某类型文章中常出现的单词是什么?某作家最常用的词汇是什么?<Harry Potter> 中最常用的短语是什么,等等. ...
- Go语言入门篇-gRPC基于golang & java简单实现
一.什么是RPC 1.简介: RPC:Remote Procedure Call,远程过程调用.简单来说就是两个进程之间的数据交互. 正常服务端的接口服务是提供给用户端(在Web开发中就是浏览器)或者 ...