Java-IO之管道(PipedInputStream和PipedOutputStream)
java中PipedInputStream和PipedOutputStream分别是管道输入流和管道输出流,它的作用是让多线程可以通过管道进行线程间的通讯,在使用管道通信时,必须将PipedInputStream和PipedOutputStream配套使用。大致的流程是:当在线程A中向PipedOutputStream中写入数据,会自动发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲区中,此时线程B通过读取PipedInputStream中的数据,实现线程的通信。
PipedInputStream类的主要函数有:
public PipedInputStream(PipedOutputStream src) public PipedInputStream(PipedOutputStream src, int pipeSize) public PipedInputStream() public PipedInputStream(int pipeSize) public void connect(PipedOutputStream src) protected synchronized void receive(int b) synchronized void receive(byte b[], int off, int len) public synchronized int read() public synchronized int read(byte b[], int off, int len) public synchronized int available()
PipedOutputStream类的主要函数有:
public PipedOutputStream(PipedInputStream snk) public PipedOutputStream() public synchronized void connect(PipedInputStream snk) public void write(int b) public void write(byte b[], int off, int len)
基于PipedInputStream和PipedOutputStream线程通信示例:
Send类:
public class Send extends Thread { private PipedOutputStream outputStream=new PipedOutputStream(); public PipedOutputStream getOutputStream() { return outputStream; } @Override public void run() { writeMessage(); } public void writeMessage() { String string="hello pipedstream"; try { outputStream.write(string.getBytes()); outputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Receiver类:
public class Receiver extends Thread{ private PipedInputStream inputStream=new PipedInputStream(); public PipedInputStream getInputStream() { return inputStream; } @Override public void run() { readMessage(); } public void readMessage() { byte[] buf=new byte[2048]; int len; try { len = inputStream.read(buf); System.out.println(new String(buf,0,len)); inputStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
Main函数:
public class Hello { public static void main(String [] args) { Send s1=new Send(); Receiver r1=new Receiver(); PipedInputStream inputStream=r1.getInputStream(); PipedOutputStream outputStream=s1.getOutputStream(); try { inputStream.connect(outputStream); s1.start(); r1.start(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
基于JDK8的PipedOutputStream的源码:
public class PipedOutputStream extends OutputStream { (but it may be a long time until the next GC). */ private PipedInputStream sink; //构造函数,连接输出流 public PipedOutputStream(PipedInputStream snk) throws IOException { connect(snk); } //构造函数,并没有连接管道输入流,在使用之前必须进行连接 public PipedOutputStream() { } //管道输出流和输入流进行连接,如果已经连接会抛出错误 public synchronized void connect(PipedInputStream snk) throws IOException { if (snk == null) { throw new NullPointerException(); } else if (sink != null || snk.connected) { throw new IOException("Already connected"); } sink = snk; snk.in = -1; snk.out = 0; snk.connected = true; } //向输入流写数据 public void write(int b) throws IOException { if (sink == null) { throw new IOException("Pipe not connected"); } sink.receive(b); } //想输入流写b,起始为off,长度为len public void write(byte b[], int off, int len) throws IOException { if (sink == null) { throw new IOException("Pipe not connected"); } else if (b == null) { throw new NullPointerException(); } else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return; } sink.receive(b, off, len); } //刷新,强制任意一个输出流都被写出 public synchronized void flush() throws IOException { if (sink != null) { synchronized (sink) { sink.notifyAll(); } } } //关闭输出流,释放资源 public void close() throws IOException { if (sink != null) { sink.receivedLast(); } } }
基于JDK8的PipedInputStream的源码:
public class PipedInputStream extends InputStream { boolean closedByWriter = false; volatile boolean closedByReader = false; boolean connected = false; Thread readSide;//读线程 Thread writeSide;//写线程 private static final int DEFAULT_PIPE_SIZE = 1024;//默认管道大小 protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE; //字节数组,循环数组,放置数据 protected byte buffer[]; //写的标志位为-1 protected int in = -1; //读的标志位为0,当in==out表示为空, protected int out = 0; //构造函数,连接输出流 public PipedInputStream(PipedOutputStream src) throws IOException { this(src, DEFAULT_PIPE_SIZE); } //构造函数,连接输出流,并设置管道大小 public PipedInputStream(PipedOutputStream src, int pipeSize)throws IOException { initPipe(pipeSize); connect(src); } //构造函数,还没有连接输出流 public PipedInputStream() { initPipe(DEFAULT_PIPE_SIZE); } //设置管道大小 public PipedInputStream(int pipeSize) { initPipe(pipeSize); } private void initPipe(int pipeSize) { if (pipeSize <= 0) { throw new IllegalArgumentException("Pipe Size <= 0"); } buffer = new byte[pipeSize]; } //连接输出流 public void connect(PipedOutputStream src) throws IOException { src.connect(this); } //读取数据 protected synchronized void receive(int b) throws IOException { checkStateForReceive(); writeSide = Thread.currentThread(); if (in == out) awaitSpace(); if (in < 0) { in = 0; out = 0; } buffer[in++] = (byte)(b & 0xFF); if (in >= buffer.length) { in = 0; } } synchronized void receive(byte b[], int off, int len) throws IOException { checkStateForReceive(); writeSide = Thread.currentThread(); int bytesToTransfer = len; while (bytesToTransfer > 0) { if (in == out) awaitSpace(); int nextTransferAmount = 0; if (out < in) { nextTransferAmount = buffer.length - in; } else if (in < out) { if (in == -1) { in = out = 0; nextTransferAmount = buffer.length - in; } else { nextTransferAmount = out - in; } } if (nextTransferAmount > bytesToTransfer) nextTransferAmount = bytesToTransfer; assert(nextTransferAmount > 0); System.arraycopy(b, off, buffer, in, nextTransferAmount); bytesToTransfer -= nextTransferAmount; off += nextTransferAmount; in += nextTransferAmount; if (in >= buffer.length) { in = 0; } } } private void checkStateForReceive() 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"); } } private void awaitSpace() throws IOException { while (in == out) { checkStateForReceive(); /* full: kick any waiting readers */ notifyAll(); try { wait(1000); } catch (InterruptedException ex) { throw new java.io.InterruptedIOException(); } } } synchronized void receivedLast() { closedByWriter = true; notifyAll(); } //从输入流中读取数据 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++] & 0xFF; if (out >= buffer.length) { out = 0; } if (in == out) { /* now empty */ in = -1; } return ret; } //从输入流中读取数据到b。其实为off,大小为len public synchronized int read(byte b[], int off, int len) throws IOException { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } /* possibly wait on the first character */ int c = read(); if (c < 0) { return -1; } b[off] = (byte) c; int rlen = 1; while ((in >= 0) && (len > 1)) { int available; if (in > out) { available = Math.min((buffer.length - out), (in - out)); } else { available = buffer.length - out; } // A byte is read beforehand outside the loop if (available > (len - 1)) { available = len - 1; } System.arraycopy(buffer, out, b, off + rlen, available); out += available; rlen += available; len -= available; if (out >= buffer.length) { out = 0; } if (in == out) { /* now empty */ in = -1; } } return rlen; } //判断是否还有数据 public synchronized int available() throws IOException { if(in < 0) return 0; else if(in == out) return buffer.length; else if (in > out) return in - out; else return in + buffer.length - out; } //关闭资源 public void close() throws IOException { closedByReader = true; synchronized (this) { in = -1; } } }
Java-IO之管道(PipedInputStream和PipedOutputStream)的更多相关文章
- 系统学习 Java IO (六)----管道流 PipedInputStream/PipedOutputStream
目录:系统学习 Java IO---- 目录,概览 PipedInputStream 类使得可以作为字节流读取管道的内容. 管道是同一 JVM 内的线程之间的通信通道. 使用两个已连接的管道流时,要为 ...
- JAVA IO之管道流总结大全(转)
要在文本框中显示控制台输出,我们必须用某种方法“截取”控制台流.换句话说,我们要有一种高效地读取写入到System.out和 System.err 所有内容的方法.如果你熟悉Java的管道流Piped ...
- Java I/O流-PipedInputStream、PipedOutputStream
一.整体代码图 PipedStreamDemo.java import java.io.*; class PipedStreamDemo { public static void main(Strin ...
- java io之管道流
一.java.io中存在一中流叫管道流,类似管道的功能.PipedOutputStream和PipedInputStream分别是管道输出流和管道输入流.这个两个流必须同时使用. 二.作用:进行两个线 ...
- java io系列04之 管道(PipedOutputStream和PipedInputStream)的简介,源码分析和示例
本章,我们对java 管道进行学习. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_04.html java 管道介绍 在java中,PipedOu ...
- Java IO: PipedInputStream
原文链接 作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) PipedInputStream可以从管道中读取字节流数据,代码如下: 01 InputSt ...
- Java IO: 管道
原文链接 作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力.所以管道也可以作为 ...
- Java IO学习--(三)通道
Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力.所以管道也可以作为数据源以及目标媒介. 你不能利用管道与不同的JVM中的线程通信(不同的进程).在概念上,Java的管道不同于U ...
- Java基础17:Java IO流总结
更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...
- 系统学习 Java IO ---- 目录,概览
Java IO 类的系统教程,原创.主要参考自英文教程 Java IO Tutorial 和 Java Doc. http://tutorials.jenkov.com/java-io/index.h ...
随机推荐
- java集合之HashMap源码解读
源自:jdk1.8.0_121 HashMap继承自AbstractMap,实现了Map.Cloneable.Serializable. HashMap内部是由数组.链表.红黑树实现的 变量 // 默 ...
- WEB中间件--Jboss未授权访问,
1,Jboss未授权访问部署木马 发现存在Jboss默认页面,点进控制页 点击 Jboss.deployment 进入应用部署页面 也可以直接输入此URL进入 http://www.ctfswiki. ...
- 剖析Vue原理&实现双向绑定MVVM
转自:http://www.w3cmark.com/2016/496.html 本文能帮你做什么? 1.了解vue的双向数据绑定原理以及核心代码模块 2.缓解好奇心的同时了解如何实现双向绑定 为了便于 ...
- LintCode题解之最长单词
这些一次遍历搞定的,套路无非都是在遍历的时候就记录数据的状态,然后根据遍历到的当前的数据的状态来修改最终结果,当遍历完了的时候结果也就确定了. public class Solution { /* * ...
- Kirill And The Game CodeForces - 842A
CodeForces - 842A 需要将除法改换成乘法进行计算 #include<bits/stdc++.h> using namespace std; int main() { lon ...
- MySQL PHP 语法
MySQL PHP 语法 MySQL 可应用于多种语言,包括 PERL, C, C++, JAVA 和 PHP. 在这些语言中,MySQL在PHP的web开发中是应用最广泛. 在本教程中我们大部分实例 ...
- VirtualBox: How to config higher screen resolution
Issue: Default Screen Resolution in Virtualbox instance is 800*600 which might be too small for gene ...
- Linux块设备加密之dm-crypt分析
相关的分析工作一年前就做完了,一直懒得写下来.现在觉得还是写下来,以来怕自己忘记了,二来可以给大家分享一下自己的研究经验. 这篇文章算是<Device Mapper代码分析>的后续篇,因为 ...
- Xcode 调试技巧 --常用命令和断点
Xcode 中的调试技巧与我们的日常开发息息相关,而这些调试技巧在我们解决Bug时,常常有事半功倍的作用,经常会用到的有各种断点 和 命令.而这些调试技巧也经常会在面试中问到,所以不知道的就来看看吧. ...
- 剑指Offer——知识点储备--Linux基本命令+Makefile
剑指Offer--知识点储备–Linux基本命令 1.linux下查看进程占用cpu的情况(top): 格式 top [-] [d delay] [q] [c] [S] [s] [i] [n] 主要参 ...