1. 通过输入/输出在线程间进行通信通常很有用。提供线程功能的类库以“管道”的形式对线程间的输入/输出提供了支持。它们在Java输入/输出类库中的对应物就是PipedWriter类(允许任务向管道写)和PipedReader类(允许不同任务从同一个管道中读取)。这个模型可以看成是“生产者 - 消费者”问题的变体,这里的管道就是一个封装好的解决方案。管道基本上是一个阻塞队列,存在于多个引入BlockingQueue之前的Java版本中。

  2. 下面是一个简单例子,两个任务使用一个管道进行通信:

    Class :

package lime.thinkingInJava._021._005._005;

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; /**
* @Author : Lime
* @Description :
* @Remark :
*/
class Sender implements Runnable{
private Random rand = new Random(47);
private PipedWriter out = new PipedWriter();
public PipedWriter getPipedWriter(){
return out;
}
public void run(){
try{
while (true){
for(char c = 'A'; c <= 'z';c++){
out.write(c);
TimeUnit.MILLISECONDS.sleep(rand.nextInt(500));
}
}
} catch (InterruptedException e) {
System.out.println(e + " Sender sleep Interrupted");
} catch (IOException e) {
System.out.println(e + " Sender write exception");
}
}
}
class Receiver implements Runnable{
private PipedReader in;
public Receiver(Sender sender) throws IOException {
in = new PipedReader(sender.getPipedWriter());
}
public void run(){
try{
while (true){
//Blocks until characters are there;
System.out.println("Read : " + (char)in.read());
}
} catch (IOException e) {
System.out.println(e + " Receiver read exception");
}
}
}
public class PipedIO {
public static void main(String[] args) throws IOException, InterruptedException {
Sender sender = new Sender();
Receiver receiver = new Receiver(sender);
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(sender);
exec.execute(receiver);
TimeUnit.SECONDS.sleep(4);
exec.shutdownNow();
}
}

  3. Console :

Read : A
Read : B
Read : C
Read : D
Read : E
Read : F
Read : G
Read : H
Read : I
Read : J
Read : K
Read : L
Read : M
Read : N
Read : O
Read : P
Read : Q
java.lang.InterruptedException: sleep interrupted Sender sleep Interrupted
java.io.InterruptedIOException Receiver read exception

  4. Sender和Receiver代表了需要互相通信两个任务。Sender创建了一个PipedWriter,它是一个单独的对象;但是对于Receiver,PipedReader的建立必须在构造器中与一个PipedWriter相关联。Sender把数据放进Writer,然后休眠一段时间(随机数)。然而,Receiver没有Sleep()和wait()。但当它调用read()时,如果没有更多的数据,管道将自动阻塞。

  注意sender和receiver是在main()中启动的,即对象构造彻底完毕以后。如果你启动了一个没有构造完毕的对象,在不同的平台上管道可能会产生不一致的行为(注意,BlockingQueue使用起来更加健壮而容易)。

  在shutdownNow()被调用时,可以看到PipedReader与普通I/O之间最重要的差异 ------ PipedReader是可中断的。如果你将in.read()调用修改为System.in.read(),那么interrupt()将不能打断read()调用。

  5. PipedWriter的wirte() 源码解析

    /**
* Writes the specified <code>char</code> to the piped output stream.
* If a thread was reading data characters from the connected piped input
* stream, but the thread is no longer alive, then an
* <code>IOException</code> is thrown.
* <p>
* Implements the <code>write</code> method of <code>Writer</code>.
*
* @param c the <code>char</code> to be written.
* @exception IOException if the pipe is
* <a href=PipedOutputStream.html#BROKEN> <code>broken</code></a>,
* {@link #connect(java.io.PipedReader) unconnected}, closed
* or an I/O error occurs.
*/
public void write(int c) throws IOException {
if (sink == null) {
throw new IOException("Pipe not connected");
}
//调用PipedReader的receive(c)方法,将c放入PipedReader的char buffer[]中
sink.receive(c);
}
    /**
* Receives a char of data. This method will block if no input is
* available.
*/
synchronized void receive(int c) throws IOException {
if (!connected) {
//判断两个I/O流连接状态
throw new IOException("Pipe not connected");
} else if (closedByWriter || closedByReader) {
//判断两个I/O流开启状态
throw new IOException("Pipe closed");
} else if (readSide != null && !readSide.isAlive()) {
//判断输入流线程是否存活
throw new IOException("Read end dead");
} //获取输出流线程
writeSide = Thread.currentThread();
while (in == out) {
//判断char buffer[] 是否已满
if ((readSide != null) && !readSide.isAlive()) {
//判断输入流状态是否存活
throw new IOException("Pipe broken");
}
/* full: kick any waiting readers */
// 间隔1000毫秒唤醒写线程 -- start
notifyAll();
try {
//阻塞1000毫秒
wait(1000);
} catch (InterruptedException ex) {
throw new java.io.InterruptedIOException();
}
// 间隔1000毫秒唤醒写线程 -- end
}
if (in < 0) {
//判断char buffer[] 为空
in = 0;
out = 0;
}
buffer[in++] = (char) c;
if (in >= buffer.length) {
in = 0;
}
}

  6. PipedRead的read() 源码解析

    /**
* Reads the next character of data from this piped stream.
* If no character is available because the end of the stream
* has been reached, the value <code>-1</code> is returned.
* This method blocks until input data is available, the end of
* the stream is detected, or an exception is thrown.
*
* @return the next character of data, or <code>-1</code> if the end of the
* stream is reached.
* @exception IOException if the pipe is
* <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
* {@link #connect(java.io.PipedWriter) unconnected}, closed,
* or an I/O error occurs.
*/
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) {
//判断char buffer[] 为空
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 */
// 间隔1000毫秒唤醒读线程 -- start
notifyAll();
try {
//阻塞1000毫秒
wait(1000);
} catch (InterruptedException ex) {
throw new java.io.InterruptedIOException();
}
// 间隔1000毫秒唤醒读线程 -- start
}
int ret = buffer[out++];
if (out >= buffer.length) {
out = 0;
}
if (in == out) {
/* now empty */
in = -1;
}
return ret;
}

  7. 鸣谢

    PipedWriter PipedReader 源码分析

啦啦啦

TIJ -- 任务间使用管道进行输入/输出的更多相关文章

  1. java 线程 生产者-消费者与队列,任务间使用管道进行输入、输出 解说演示样例 --thinking java4

    package org.rui.thread.block2; import java.io.BufferedReader; import java.io.IOException; import jav ...

  2. shell 通配符,管道符,输入/输出重定向,命令置换

    1. echo 输出   [echo 输出的内容 ]把内容输出到终端上 如果字符串使用双引号,echo命令原样输出   [ echo "hello       world" ]  ...

  3. 输入/输出系统的四种不同工作方式对CPU利用率比较

    程序控制工作方式:输入/输出完全由CPU控制,整个I/O过程中CPU必须等待其完成,因此对CPU的能力限制很大,利用率较低 程序中断工作方式:CPU不再定期查询I/O系统状态,而是当需要I/O处理时再 ...

  4. JAVA里面的IO流(一)分类1(字节/字符和输入/输出)

      java.io包中定义了多个流类型(流或抽象类)来实现输入/输出功能:可以从不同的角度对其进行分类: 按数据流的方向不同可以分为输入流和输出流 从文件读数据为输入流:往文件写数据为输出流 按处理数 ...

  5. [转]C语言文件输入/输出ACM改进版(freopen函数)

    C语言文件输入/输出ACM改进版(freopen函数) 2009年5月27日 10:379,457 浏览数发表评论阅读评论   文章作者:姜南(Slyar) 文章来源:Slyar Home (www. ...

  6. ubuntu12.04软件中心打开错误和 ubuntu 包管理之“:E: 读错误 - read (5: 输入/输出错误) E: 无法解析或打开软件包的列表或是状态文件。”的解决

    执行ubuntu软讲中心时打不开.老是崩溃,从终端也下载不了软件. 执行包管理的update或者search等等会报错: E: 读错误 - read (5: 输入/输出错误) E: 无法解析或打开软件 ...

  7. A Byte of Python 笔记(10)输入/输出:文件和储存器

    第12章  输入/输出 大多数情况下,我们需要程序与用户交互.从用户得到输入,然后打印一些结果. 可以分别使用 raw_input 和 print 语句来完成这些功能.对于输出,可以使用多种多样的 s ...

  8. Python基础学习笔记---5.输入\输出 I\O文件操作目录

    在很多时候,你会想要让你的程序与用户(可能是你自己)交互.你会从用户那里得到输入,然后打印一些结果.我们可以分别使用 raw_input 和 print 语句来完成这些功能.对于输出,你也可以使用多种 ...

  9. rm: 无法删除 "xxxxx.o" : 输入/输出错误.

    rm: 无法删除 "xxxxx.o" : 输入/输出错误. 碰到无法删除的文件,以为完蛋了,要重装. 后面重启一下就可以了

随机推荐

  1. python实现23种设计模式

    本文源码寄方于github:https://github.com/w392807287/Design_pattern_of_python 参考文献: <大话设计模式>——吴强 <Py ...

  2. 初识hibernate——环境搭建

    一  配置过程 1. 创建一个项目 2. 导包    required里的包 optional里的c3p0连接池的三个包 数据库驱动包 Junit 3.创建Hibernate的配置文件(hiberna ...

  3. goland 中国 caisy qq Czx123456

    goland 中国 caisy  qq  Czx123456

  4. RealTek WiFi 模块 RTL8710AF RTL8711AF RTL8711AM RTL8195AM

    瑞昱 8710 是一个完整且自成体系的 WiFi 网络解决方案, 能够独立运行,也可以作为从机搭载于其他主机 MCU 运行. 瑞昱 8710 在搭载应用并作为设备中唯⼀的应⽤处理器时,能够直接从外接闪 ...

  5. 推荐一个好工具:P/Invoke Interop Assistant【转】

    原文地址 :http://write.blog.csdn.net/postedit 在从托管代码里面调用非托管代码的时候,经常会翻阅MSDN找到需要调用的这个程序集里面的关于需要调用方法的签名,还要特 ...

  6. Translate Angular >=4 with ngx-translate and multiple modules

    原文:https://medium.com/@lopesgon/translate-angular-4-with-ngx-translate-and-multiple-modules-7d9f0252 ...

  7. nrm管理npm源

    npm源:npm install命令下载需要依赖包的服务器地址,默认是 npm ---- https://registry.npmjs.org/ 而国外的源速度太慢,所以我们一般都用国内的淘宝源tao ...

  8. RobotFrameWork系列免费课程-开课了~

    1. 背景介绍 有一段时间没有发表过文章了,一方面除了自己确实变得懒惰外,另一方面也确实有其它事情,无法抽出闲余时间来坚持写下去. 之前在博客园中,发表了关于<公开课一:Robot FrameW ...

  9. 物联网全景动态图谱2.0|PaaS物联网平台汇总(上篇)

    物联网智库 原创 物联网智库 整理发布 转载请注明来源和出处 ------   [导读]   ------ 毫无疑问,2018年物联网对行业的深度变革才刚刚开启. 物联网产业链企业的质与量将进入全面爆 ...

  10. SNF快速开发平台成长史V4.5-Spring.Net.Framework-SNF软件开发机器人

    SNF快速开发平台成长史 SNF框架CS\BS 视频教程 https://pan.baidu.com/s/1dFegFKX SNF开发机器人教程:链接:https://pan.baidu.com/s/ ...