文档章节

Java IO类库之PipedWriter

 老韭菜
发布于 08/15 14:22
字数 1030
阅读 0
收藏 0

一、PipedWriter介绍

    PipedWriter是字符管道输出流,继承自Writer,功能与PipedOutputStream类似,通过与PipedReader组合使用实现类似管道的功能,在多线程环境下,一个线程使用PipedWriter写入数据,通过管道将数据传递到管道另一端的字符输入流内部缓冲区(实际是通过当前字符管道输出流绑定的字符管道输入流对象sink的receive方法将数据存储到字符输入流的内部字符缓冲区实现的),其他线程去读该内部缓冲区的字符数据,实现线程间通信。

二、PipedWriter类成员变量

package java.io;

public class PipedWriter extends Writer {

    /** 管道绑定的字符输入流对象 **/
    private PipedReader sink;

    /* 
     * 当前管道字符输出流的状态,独立于管道另一端字符输入流的状态
     */
    private boolean closed = false;

}

三、PipedWriter源码分析

1 - 构造函数

   /**
    * 构造函数,调用connect为当前对象与指定字符管道输入流对象建立连接
    */
   public PipedWriter(PipedReader snk)  throws IOException {
        connect(snk);
    }

    /**
     * 构造函数,空实现,还没与管道的字符输入流建立连接,在使用之前必须先建立连接无论是管道数据接收端PipedReader还是
     * 还是数据写入端PipedWriter调用connect建立连接
     */
    public PipedWriter() {
    }

    PipedWriter的构造函数逻辑非常简单,两种构造函数一种什么都没做只是创建一个未建立管道连接的对象,另一个构造函数在实例化的同时调用connect创建了与指定字符管道输入流对象的管道连接,之后PipedWriter主要是基于这个指定的管道输入流对象操作管道数据。

2 - void write(int c)方法 - 写入单个字符

    public void write(int c)  throws IOException {
        if (sink == null) {
            throw new IOException("Pipe not connected");
        }
        sink.receive(c);
    }

    方法逻辑很简单就是在开头做了管道绑定的接收端字符管道输入流对象sink的判空,若不为空则调用它的receive方法接收写入的单个字符c,receive的内部方法逻辑可参照上篇PipedReader对于receive方法的解析

3 - 其他成员方法

    /**
     * 为当前管道输出流对象连接指定的管道输入流对象snk,若当前管道输出流之前已经建立与其他字符管道输入流的连接则抛出
     * IOException异常
     */
    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;
    }


    /**
     * 将指定字符数组cbuf从off位置开始len个字符写入管道绑定的字符管道输入流对象内部缓冲区中
     * 如果一个线程正在读取连接的字符管道输入流内部缓冲区字节数据,这时候当前线程挂掉那么会抛出一个IO异常
     */
    public void write(char cbuf[], int off, int len) throws IOException {
        //管道绑定的字符管道输入流对象为空
        if (sink == null) {
            throw new IOException("Pipe not connected");
        } 
        /** 校验字符数组起始位置参数off **/
        else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) {
            throw new IndexOutOfBoundsException();
        }
        //将字符数组数据写入管道绑定的字符输入流内部缓冲区
        sink.receive(cbuf, off, len);
    }

    /**
     * 刷新管道输出流,主要是通过唤醒管道输入流等待读取线程读取数据实现刷新的。
     */
    public synchronized void flush() throws IOException {
        if (sink != null) {
            if (sink.closedByReader || closed) {
                throw new IOException("Pipe closed");
            }
            synchronized (sink) {
                sink.notifyAll();
            }
        }
    }

    /**
     * 关闭当前管道输出流对象,释放与此有关的系统资源,实际是调用绑定的管道输入流对象sink的reveivedLast方法
     * 更新sink管道写入端状态成员变量closedByWriter并唤醒其他等待线程
     */
    public void close()  throws IOException {
        closed = true;
        if (sink != null) {
            sink.receivedLast();
        }
    }

 

© 著作权归作者所有

共有 人打赏支持
粉丝 11
博文 64
码字总数 107681
作品 0
杭州
后端工程师
InputStream和Reader的区别

java.io.Reader 和 java.io.InputStream 组成了Java 输入类。Reader 用于读入16位字符,也就是Unicode 编码的字符;而 InputStream 用于读入 ASCII 字符和二进制数据。 Reader支持16位的Uni...

SibylY
2013/08/14
0
0
Java_io体系之PipedWriter、PipedReader

Javaio体系之PipedWriter、PipedReader简介、走进源码及示例——14 这两个类必须配套来使用,一般是用于两个线程之间的通信,想了一下其实就是一个线程往buf数组写,另一个线程从这个buf数组...

z_jordon
2015/04/28
0
0
有效选择七个关于Java的JSON开源类库

April 4, 2014 By Constantin Marian Alin 翻译:无若 (英语原文:http://www.developer.com/lang/jscript/top-7-open-source-json-binding-providers-available-today.html) 简介 JSON是J......

无若
2014/04/19
0
1
Java多线程学习(五)线程间通信知识点补充

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
04/16
0
0
《Kotin 极简教程》第15章 Kotlin 文件IO操作、正则表达式与多线程

第15章 Kotlin 文件IO操作与多线程 《Kotlin极简教程》正式上架: 点击这里 > 去京东商城购买阅读 点击这里 > 去天猫商城购买阅读 非常感谢您亲爱的读者,大家请多支持!!!有任何问题,欢迎...

程序员诗人
2017/07/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

使用rancher管理docker并部署springCloud项目的其中一个服务

一、先来个简单的 1.安装docker 2.安装eureka——运行docker命令安装 3.安装eureka——运行dokcer镜像安装 (1)构建eureka的镜像,网易云的docker镜像比较全一些,也可以去https://hub.docke...

monroeCode
6分钟前
0
0
理论与实践:如何从Hadoop迁移到MaxCompute

摘要:MaxCompute大数据计算服务,能提供快速、完全托管的PB级数据仓库解决方案,能够使用户经济且高效地分析处理海量数据。而用户往往之前使用了Hadoop实现大数据计算任务,在选择了阿里云大...

阿里云云栖社区
6分钟前
1
0
mysql: utf8 && utf8mb4

https://mathiasbynens.be/notes/mysql-utf8mb4 临时收藏

阿dai
18分钟前
0
0
面试宝典系列-nginx限流

Nginx自身有的请求限制模块ngx_http_limit_req_module、流量限制模块ngx_stream_limit_conn_module基于令牌桶算法,可以方便的控制令牌速率,自定义调节限流,实现基本的限流控制。 如何Ngi...

suyain
18分钟前
0
0
下拉框选择数据过滤?

需求:下拉框数据新增一条数据,已选择的不能再重新被选择 数据:存放表格数据的数组 scoreTable 下拉框数据 catorgaryArr 定义一个已经选择了的id数组 catorgaryIds 实现: arr 使用来保存每...

西园里的猫
23分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部