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 ...
随机推荐
- 记录一次widora sdk编译ipk 实战编译redis
因为业务需求,需要用到redis存储一点简单的数据,因为redis有良好的哈希机制,可以完美实现我的某些需求,但openwrt官方提供memcached的ipk并没有提供redis,没办法,只能自 ...
- 前端实现搜索历史和清空历史(angularjs+ionic)
要实现的页面效果: 1.显示历史搜索, 2.最近搜索的排在最前, 2.最多显示8条历史 4.清空历史记录 思路: 1.首先显示历史记录需要一个数组searchItems,通过ng-repeat显示每一 ...
- MySQL查看数据库信息
使用MySQL时,需要了解当前数据库的情况,例如当前的数据库大小.字符集.用户等等.下面总结了一些查看数据库相关信息的命令 1:查看显示所有数据库 mysql> show databases; ...
- vue+node.js+webpack开发微信公众号功能填坑——组件按需引入
初次开发微信公众号,整体框架是经理搭建,小喽喽只是实现部分功能,整体页面效果 整个页面使用两个组件:布局 FlexBox,搜索框 Search,demo文档 http://vue.ydui.org/d ...
- centos 7 破解密码
CentOS 7 root密码的重置方式和CentOS 6完全不一样,CentOS 7与之前的版本6变化还是比较大的,以进入单用户模式修改root密码为例. 1.重启开机按esc 2.按e ...
- Node.js 多进程
我们都知道 Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核 cpu 的系统上创建多个子进程,从而提高性能. 每个子进程总是带有三个流对象:child.st ...
- MyEclipse的Debug模式启动缓慢
打开breakpoints veiw,右键-> Remove all,重启下服务器就OK了 -–下面有个"顶"字,你懂得O(∩_∩)O哈哈~ -–乐于分享,共同进步! -–更 ...
- MyBatis批量新增和更新
之前有开发任务一个接口里面有大量的数据新增和更新操作,导致十分缓慢.使用了批量操作之后速度有明显提升,几乎百倍千倍的速度提升. 博主之前统计过,通过普通接口一次数据库插入大概需要200ms,对于大量新 ...
- Android开发技巧——定制仿微信图片裁剪控件
拍照--裁剪,或者是选择图片--裁剪,是我们设置头像或上传图片时经常需要的一组操作.上篇讲了Camera的使用,这篇讲一下我对图片裁剪的实现. 背景 下面的需求都来自产品. 裁剪图片要像微信那样,拖动 ...
- Redis中的关系查询
本文对Redis如何保存关系型数据,以及如何对其匹配.范围.模糊查询进行举例讲解,其中模糊查询功能基于最新的2.8.9以后版本. 1 关系型数据的存储 以Staff对象为例,在关系型数据库或类似Gri ...