Java_io体系之PipedWriter、PipedReader简介、走进源码及示例——14
Java_io体系之PipedWriter、PipedReader简介、走进源码及示例——14
——管道字符输出流、必须建立在管道输入流之上、所以先介绍管道字符输出流。可以先看示例或者总结、总结写的有点Q、不喜可无视、有误的地方指出则不胜感激。
一:PipedWriter
1、类功能简介:
管道字符输出流、用于将当前线程的指定字符写入到与此线程对应的管道字符输入流中去、所以PipedReader(pr)、PipedWriter(pw)必须配套使用、缺一不可。管道字符输出流的本质就是调用pr中的方法将字符或者字符数组写入到pr中、这一点是与众不同的地方。所以pw中的方法很少也很简单、主要就是负责将传入的pr与本身绑定、配对使用、然后就是调用绑定的pr的写入方法、将字符或者字符数组写入到pr的缓存字符数组中。
2、PipedWriter API简介:
A:关键字
- private PipedReader sink; 与此PipedWriter绑定的PipedReader
- private boolean closed = false; 标示此流是否关闭。
B:构造方法
- PipedWriter(PipedReader snk) 根据传入的PipedReader构造pw、并将pr与此pw绑定
- PipedWriter() 创建一个pw、在使用之前必须与一个pr绑定
C:一般方法
- synchronized void connect(PipedReader snk) 将此pw与一个pr绑定
- void close() 关闭此流。
- synchronized void connect(PipedReader snk) 将此pw与一个pr绑定
- synchronized void flush() flush此流、唤醒pr中所有等待的方法。
- void write(int c) 将一个整数写入到与此pw绑定的pr的缓存字符数组buf中去
- void write(char cbuf[], int off, int len) 将cbuf的一部分写入pr的buf中去
3、源码分析
- package com.chy.io.original.code;
- import java.io.IOException;
- public class PipedWriter extends Writer {
- //与此PipedWriter绑定的PipedReader
- private PipedReader sink;
- //标示此流是否关闭。
- private boolean closed = false;
- /**
- * 根据传入的PipedReader构造pw、并将pr与此pw绑定
- */
- public PipedWriter(PipedReader snk) throws IOException {
- connect(snk);
- }
- /**
- * 创建一个pw、在使用之前必须与一个pr绑定
- */
- public PipedWriter() {
- }
- /**
- * 将此pw与一个pr绑定
- */
- 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;
- }
- /**
- * 将一个整数写入到与此pw绑定的pr的缓存字符数组buf中去
- */
- public void write(int c) throws IOException {
- if (sink == null) {
- throw new IOException("Pipe not connected");
- }
- sink.receive(c);
- }
- /**
- * 将cbuf的一部分写入pr的buf中去
- */
- public void write(char cbuf[], int off, int len) throws IOException {
- if (sink == null) {
- throw new IOException("Pipe not connected");
- } else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) {
- throw new IndexOutOfBoundsException();
- }
- sink.receive(cbuf, off, len);
- }
- /**
- * flush此流、唤醒pr中所有等待的方法。
- */
- public synchronized void flush() throws IOException {
- if (sink != null) {
- if (sink.closedByReader || closed) {
- throw new IOException("Pipe closed");
- }
- synchronized (sink) {
- sink.notifyAll();
- }
- }
- }
- /**
- * 关闭此流。
- */
- public void close() throws IOException {
- closed = true;
- if (sink != null) {
- sink.receivedLast();
- }
- }
- }
4、实例演示:
因为PipedWriter必须与PipedReader结合使用、所以将两者的示例放在一起。
二:PipedReader
1、类功能简介:
管道字符输入流、用于读取对应绑定的管道字符输出流写入其内置字符缓存数组buffer中的字符、借此来实现线程之间的通信、pr中专门有两个方法供pw调用、receive(char c)、receive(char[] b, int off, intlen)、使得pw可以将字符或者字符数组写入pr的buffer中、
2、PipedReader API简介:
A:关键字
- boolean closedByWriter = false; 标记PipedWriter是否关闭
- boolean closedByReader = false; 标记PipedReader是否关闭
- boolean connected = false; 标记PipedWriter与标记PipedReader是否关闭的连接是否关闭
- Thread readSide; 拥有PipedReader的线程
- Thread writeSide; 拥有PipedWriter的线程
- private static final int DEFAULT_PIPE_SIZE = 1024; 用于循环存放PipedWriter写入的字符数组的默认大小
- char buffer[]; 用于循环存放PipedWriter写入的字符数组
- int in = -1; buf中下一个存放PipedWriter调用此PipedReader的receive(int c)时、c在buf中存放的位置的下标。此为初始状态、即buf中没有字符
- int out = 0; buf中下一个被读取的字符的下标
B:构造方法
- PipedReader(PipedWriter src) 使用默认的buf的大小和传入的pw构造pr
- PipedReader(PipedWriter src, int pipeSize) 使用指定的buf的大小和传入的pw构造pr
- PipedReader() 使用默认大小构造pr
- PipedReader(int pipeSize) 使用指定大小构造pr
C:一般方法
- void close() 清空buf中数据、关闭此流。
- void connect(PipedWriter src) 调用与此流绑定的pw的connect方法、将此流与对应的pw绑定
- synchronized boolean ready() 查看此流是否可读
- synchronized int read() 从buf中读取一个字符、以整数形式返回
- synchronized int read(char cbuf[], int off, int len) 将buf中读取一部分字符到cbuf中。
- synchronized void receive(int c) pw调用此流的此方法、向pr的buf以整数形式中写入一个字符。
- synchronized void receive(char c[], int off, int len) 将c中一部分字符写入到buf中。
- synchronized void receivedLast() 提醒所有等待的线程、已经接收到了最后一个字符。
3、源码分析
- package com.chy.io.original.code;
- import java.io.IOException;
- public class PipedReader extends Reader {
- boolean closedByWriter = false;
- boolean closedByReader = false;
- boolean connected = false;
- Thread readSide;
- Thread writeSide;
- /**
- * 用于循环存放PipedWriter写入的字符数组的默认大小
- */
- private static final int DEFAULT_PIPE_SIZE = 1024;
- /**
- * 用于循环存放PipedWriter写入的字符数组
- */
- char buffer[];
- /**
- * buf中下一个存放PipedWriter调用此PipedReader的receive(int c)时、c在buf中存放的位置的下标。
- * in为-1时、说明buf中没有可读取字符、in=out时已经存满了。
- */
- int in = -1;
- /**
- * buf中下一个被读取的字符的下标
- */
- int out = 0;
- /**
- * 使用默认的buf的大小和传入的pw构造pr
- */
- public PipedReader(PipedWriter src) throws IOException {
- this(src, DEFAULT_PIPE_SIZE);
- }
- /**
- * 使用指定的buf的大小和传入的pw构造pr
- */
- public PipedReader(PipedWriter src, int pipeSize) throws IOException {
- initPipe(pipeSize);
- connect(src);
- }
- /**
- * 使用默认大小构造pr
- */
- public PipedReader() {
- initPipe(DEFAULT_PIPE_SIZE);
- }
- /**
- * 使用指定大小构造pr
- */
- public PipedReader(int pipeSize) {
- initPipe(pipeSize);
- }
- //初始化buf大小
- private void initPipe(int pipeSize) {
- if (pipeSize <= 0) {
- throw new IllegalArgumentException("Pipe size <= 0");
- }
- buffer = new char[pipeSize];
- }
- /**
- * 调用与此流绑定的pw的connect方法、将此流与对应的pw绑定
- */
- public void connect(PipedWriter src) throws IOException {
- src.connect(this);
- }
- /**
- * pw调用此流的此方法、向pr的buf以整数形式中写入一个字符。
- */
- synchronized void receive(int c) throws IOException {
- if (!connected) {
- throw new IOException("Pipe not connected");
- } else if (closedByWriter || closedByReader) {
- throw new IOException("Pipe closed");
- } else if (readSide != null && !readSide.isAlive()) {
- throw new IOException("Read end dead");
- }
- writeSide = Thread.currentThread();
- while (in == out) {
- if ((readSide != null) && !readSide.isAlive()) {
- throw new IOException("Pipe broken");
- }
- //buf中写入的被读取完、唤醒所有此对象监控的线程其他方法、如果一秒钟之后还是满值、则再次唤醒其他方法、直到buf中被读取。
- notifyAll();
- try {
- wait(1000);
- } catch (InterruptedException ex) {
- throw new java.io.InterruptedIOException();
- }
- }
- //buf中存放第一个字符时、将字符在buf中存放位置的下标in初始化为0、读取的下标也初始化为0、准备接受写入的第一个字符。
- if (in < 0) {
- in = 0;
- out = 0;
- }
- buffer[in++] = (char) c;
- //如果buf中放满了、则再从头开始存放。
- if (in >= buffer.length) {
- in = 0;
- }
- }
- /**
- * 将c中一部分字符写入到buf中。
- */
- synchronized void receive(char c[], int off, int len) throws IOException {
- while (--len >= 0) {
- receive(c[off++]);
- }
- }
- /**
- * 提醒所有等待的线程、已经接收到了最后一个字符、PipedWriter已关闭。用于PipedWriter的close()方法.
- */
- synchronized void receivedLast() {
- closedByWriter = true;
- notifyAll();
- }
- /**
- * 从buf中读取一个字符、以整数形式返回
- */
- public synchronized int read() throws IOException {
- if (!connected) {
- throw new IOException("Pipe not connected");
- } else if (closedByReader) {
- throw new IOException("Pipe closed");
- } else if (writeSide != null && !writeSide.isAlive() && !closedByWriter && (in < 0)) {
- throw new IOException("Write end dead");
- }
- readSide = Thread.currentThread();
- int trials = 2;
- while (in < 0) {
- if (closedByWriter) {
- /* closed by writer, return EOF */
- return -1;
- }
- if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
- throw new IOException("Pipe broken");
- }
- /* might be a writer waiting */
- notifyAll();
- try {
- wait(1000);
- } catch (InterruptedException ex) {
- throw new java.io.InterruptedIOException();
- }
- }
- int ret = buffer[out++];
- if (out >= buffer.length) {
- out = 0;
- }
- if (in == out) {
- /* now empty */
- in = -1;
- }
- return ret;
- }
- /**
- * 将buf中读取一部分字符到cbuf中。
- */
- public synchronized int read(char cbuf[], int off, int len) throws IOException {
- if (!connected) {
- throw new IOException("Pipe not connected");
- } else if (closedByReader) {
- throw new IOException("Pipe closed");
- } else if (writeSide != null && !writeSide.isAlive() && !closedByWriter && (in < 0)) {
- throw new IOException("Write end dead");
- }
- if ((off < 0) || (off > cbuf.length) || (len < 0) ||
- ((off + len) > cbuf.length) || ((off + len) < 0)) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
- /* possibly wait on the first character */
- int c = read();
- if (c < 0) {
- return -1;
- }
- cbuf[off] = (char)c;
- int rlen = 1;
- while ((in >= 0) && (--len > 0)) {
- cbuf[off + rlen] = buffer[out++];
- rlen++;
- //如果读取的下一个字符下标大于buffer的size、则重置out、从新开始从第一个开始读取。
- if (out >= buffer.length) {
- out = 0;
- }
- //如果下一个写入字符的下标与下一个被读取的下标相同、则清空buf
- if (in == out) {
- /* now empty */
- in = -1;
- }
- }
- return rlen;
- }
- /**
- * 查看此流是否可读、看各个线程是否关闭、以及buffer中是否有可供读取的字符。
- */
- public synchronized boolean ready() throws IOException {
- if (!connected) {
- throw new IOException("Pipe not connected");
- } else if (closedByReader) {
- throw new IOException("Pipe closed");
- } else if (writeSide != null && !writeSide.isAlive()
- && !closedByWriter && (in < 0)) {
- throw new IOException("Write end dead");
- }
- if (in < 0) {
- return false;
- } else {
- return true;
- }
- }
- /**
- * 清空buf中数据、关闭此流。
- */
- public void close() throws IOException {
- in = -1;
- closedByReader = true;
- }
- }
4、实例演示:
- package com.chy.io.original.thread;
- import java.io.IOException;
- import java.io.PipedWriter;
- @SuppressWarnings("all")
- public class CharSenderThread implements Runnable {
- private PipedWriter pw = new PipedWriter();
- public PipedWriter getPipedWriter(){
- return pw;
- }
- @Override
- public void run() {
- //sendOneChar();
- //sendShortMessage();
- sendLongMessage();
- }
- private void sendOneChar(){
- try {
- pw.write("a".charAt(0));
- pw.flush();
- pw.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private void sendShortMessage() {
- try {
- pw.write("this is a short message from CharSenderThread !".toCharArray());
- pw.flush();
- pw.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private void sendLongMessage(){
- try {
- char[] b = new char[1028];
- //生成一个长度为1028的字符数组、前1020个是1、后8个是2。
- for(int i=0; i<1020; i++){
- b[i] = 'a';
- }
- for (int i = 1020; i <1028; i++) {
- b[i] = 'b';
- }
- pw.write(b);
- pw.flush();
- pw.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
用于接收字符的线程: CharReceiveThread
- package com.chy.io.original.thread;
- import java.io.IOException;
- import java.io.PipedReader;
- @SuppressWarnings("all")
- public class CharReceiverThread extends Thread {
- private PipedReader pr = new PipedReader();
- public PipedReader getPipedReader(){
- return pr;
- }
- @Override
- public void run() {
- //receiveOneChar();
- //receiveShortMessage();
- receiverLongMessage();
- }
- private void receiveOneChar(){
- try {
- int n = pr.read();
- System.out.println(n);
- pr.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private void receiveShortMessage() {
- try {
- char[] b = new char[1024];
- int n = pr.read(b);
- System.out.println(new String(b, 0, n));
- pr.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- private void receiverLongMessage(){
- try {
- char[] b = new char[2048];
- int count = 0;
- while(true){
- count = pr.read(b);
- for (int i = 0; i < count; i++) {
- System.out.print(b[i]);
- }
- if(count == -1)
- break;
- }
- pr.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- package com.chy.io.original.test;
- import java.io.IOException;
- import java.io.PipedReader;
- import java.io.PipedWriter;
- import com.chy.io.original.thread.CharReceiverThread;
- import com.chy.io.original.thread.CharSenderThread;
- public class PipedWriterAndPipedReaderTest {
- public static void main(String[] args) throws IOException{
- CharSenderThread cst = new CharSenderThread();
- CharReceiverThread crt = new CharReceiverThread();
- PipedWriter pw = cst.getPipedWriter();
- PipedReader pr = crt.getPipedReader();
- pw.connect(pr);
- /**
- * 想想为什么下面这样写会报Piped not connect异常 ?
- */
- //new Thread(new CharSenderThread()).start();
- //new CharReceiverThread().start();
- new Thread(cst).start();
- crt.start();
- }
- }
总结:
PipedReader、PipedWriter两者的结合如鸳鸯一般、离开哪一方都不能继续存在、同时又如连理枝一般、PipedWriter先通过connect(PipedReader sink)来确定关系、并初始化PipedReader状态、告诉PipedReader只能属于这个PipedWriter、connect =true、当想赠与PipedReader字符时、就直接调用receive(char c) 、receive(char[] b, int off, int len)来将字符或者字符数组放入pr的存折buffer中。站在PipedReader角度上、看上哪个PipedWriter时就暗示pw、将主动权交给pw、调用pw的connect将自己给他去登记。当想要花(将字符读取到程序中)字符了就从buffer中拿、但是自己又没有本事挣字符、所以当buffer中没有字符时、自己就等着、并且跟pw讲没有字符了、pw就会向存折(buffer)中存字符、当然、pw不会一直不断往里存、当存折是空的时候也不会主动存、怕花冒、就等着pr要、要才存。过到最后两个只通过buffer来知道对方的存在与否、每次从buffer中存或者取字符时都会看看对方是否安康、若安好则继续生活、若一方不在、则另一方也不愿独存!
更多IO内容:java_io 体系之目录
Java_io体系之PipedWriter、PipedReader简介、走进源码及示例——14的更多相关文章
- Java_io体系之BufferedWriter、BufferedReader简介、走进源码及示例——16
Java_io体系之BufferedWriter.BufferedReader简介.走进源码及示例——16 一:BufferedWriter 1.类功能简介: BufferedWriter.缓存字符输 ...
- Java_io体系之RandomAccessFile简介、走进源码及示例——20
Java_io体系之RandomAccessFile简介.走进源码及示例——20 RandomAccessFile 1. 类功能简介: 文件随机访问流.关心几个特点: 1.他实现的接口不再 ...
- java io系列13之 BufferedOutputStream(缓冲输出流)的认知、源码和示例
本章内容包括3个部分:BufferedOutputStream介绍,BufferedOutputStream源码,以及BufferedOutputStream使用示例. 转载请注明出处:http:// ...
- Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装
原文:Linux内核分析(一)---linux体系简介|内核源码简介|内核配置编译安装 Linux内核分析(一) 从本篇博文开始我将对linux内核进行学习和分析,整个过程必将十分艰辛,但我会坚持到底 ...
- Scala 深入浅出实战经典 第41讲:List继承体系实现内幕和方法操作源码揭秘
Scala 深入浅出实战经典 第41讲:List继承体系实现内幕和方法操作源码揭秘 package com.parllay.scala.dataset /** * Created by richard ...
- ThreadLocal 简介 案例 源码分析 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Java生鲜电商平台-电商会员体系系统的架构设计与源码解析
Java生鲜电商平台-电商会员体系系统的架构设计与源码解析 说明:Java生鲜电商平台中会员体系作为电商平台的基础设施,重要性不容忽视.我去年整理过生鲜电商中的会员系统,但是比较粗,现在做一个最好的整 ...
- java io系列12之 BufferedInputStream(缓冲输入流)的认知、源码和示例
本章内容包括3个部分:BufferedInputStream介绍,BufferedInputStream源码,以及BufferedInputStream使用示例. 转载请注明出处:http://www ...
- java io系列15之 DataOutputStream(数据输出流)的认知、源码和示例
本章介绍DataOutputStream.我们先对DataOutputStream有个大致认识,然后再深入学习它的源码,最后通过示例加深对它的了解. 转载请注明出处:http://www.cnblog ...
随机推荐
- Oracle 学习笔记(一)Oracle的基本介绍与语法
1.1 Oracle基础知识 1.1.1 介绍 Oracle数据库的主要特点: 支持多用户.大事务量的事务处理 在保持数据安全性和完整性方面性能优越 支持分布式数据处理 具有可移植性 1.1.2 Or ...
- grunt -- javascript自动化工具
grunt 是一个基于npm,node.js 用js编写的工具框架,可以自动完成一些重复性的任务(如合并文件,语法检查,压缩代码), grunt拥有庞大的插件库,可以满足各种自动化批处理需求,常用的插 ...
- 自己动手写easyui的checkbox
最近项目中用到了easyui这个框架,找了一圈也没有找到checkbox list控件,被迫只能自己实现了,为了便于复用,自己封装了下,有需要的,直接拿去用吧.有意见或建议的,欢迎指教啊. 调用示例 ...
- form表单提交
1.form表单提交.html页面失败 <%--客户端form--%> <form id="form2" action="LoginOne.html&q ...
- maven自动下载jar包
只需要修改pom文件即可.需要哪个jar包,在pom中就配置哪个(还包括手动向仓库中添加) 例如 http://blog.csdn.net/beyondlpf/article/details/8592 ...
- java第一天的疑问
1字节 的 byte 2字节 的 char 精度 byte<short<char<int<long<float<double 随便打个整数默认为int 随便打个小数 ...
- 逆天的IE7中,绝对定位元素之间的遮盖问题
个人比较支持IE9以上的版本,认为他们的样式和效果都是比较人性化的,不过很多时候还是不得不考虑其他版本浏览器的感受,这里IE6就不用考虑他了,这货简直就是IT史上的奇葩,这里要说一个IE7的绝对定位和 ...
- Mysql中的DQL查询语句
----------------1.查询所有列 --查询 学生 表所有记录(行) select *from 学生 --带条件的查询 select *from 学生 where 年龄>19 --- ...
- js实现数组内元素随机排序
其实蛮容易实现的,关键是简洁与否,下面是我自己写的. function randomSort(a){ var arr = a, random = [], len = arr.length; for ( ...
- sudo gedit xx warning
When I sue command "sudo gedit xx", it appeas several warning: gedit:): IBUS-WARNING **: T ...