008-八、网络编程之多线程之管道流
引言
在java
语言中提供了很多输入与输出流,使我们方便了对数据进行操作,其中管道流是一种特殊的流,用于在不同线程间直接传输数据。一个线程发送到输出管道,另一个线程从输入管道中读取数据。通过使用管道,实现不同线程间的通讯,而无须借助临时文件之类的东西了。
在jdk中提供了4个类来使用线程间可以进行通讯:
一堆字节流管道流和一堆字符管道流
PipedInputStream
PipedOutputStream
PipedReader
PipedWriter
字节管道流
一般大家都是知道的只要是流基本上都是成对成对出现的,一边写入一遍读取。现在首先讲解一下 PipedInputStream
和 PipedOutputStream
这对管道流使用步骤。
建立管道输入端和输出端的连接,必须首先创建一个 PipedOutputStream
对象,然后创建一个 PipedInputStream
对象。如下:
PipedOutputStream out = null;
PipedInputStream in = null;
对象建立好以后使用 connect()
方法将二者建立连接
out.connect(in);
该方法在 PipedOutputStream
、PipedInputStream
当中都有,随便调用那个来建立连接都可以,但注意只能建立一次连接,重复建立会抛异常。
不使用 connect()
方法也是可以建立连接的,方法如下:
out = new PipedOutputStream(in );
一旦建立了管道,就可以像操作文件一样对管道进行数据读写。
下面线程配合管道流的使用代码编写。
/**
* 写入线程
*/
public class PipedThreadOut implements Runnable {
/**
* 管道输出流
*/
private PipedOutputStream out;
/**
* 构造函数
* @param out
*/
public PipedThreadOut(PipedOutputStream out) {
this.out = out;
}
/**
* 写入数据
*/
private void write() {
String data = "我是pipedOutputStream流,写入数据了!!!";
try {
this.out.write(data.getBytes());
System.out.println("写入数据为:"+data);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
this.out.close();//关闭输出流
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
//开始写入
this.write();
}
}
/**
* 读取线程
*/
class PipedThreadIn implements Runnable {
/**
* 管道输出流
*/
private PipedInputStream in;
/**
* 构造函数
* @param in
*/
public PipedThreadIn(PipedInputStream in) {
this.in = in;
}
/**
* 读取数据
*/
private void read() {
//定义一个缓冲区
byte[] b = new byte[1024];
//记录读取字节数
int len;
String data = "";
try {
//开始读取
while ((len = this.in.read(b)) > 0) {
data += new String(b,0,len);
}
System.out.println("读取数据为:" + data);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
this.in.close();//关闭读取流
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("=====================================");
}
@Override
public void run() {
//开始读取
this.read();
}
}
//调用代码
public class PipedThreadTest {
public static void main(String[] args) throws IOException, InterruptedException {
//创建写入流
PipedOutputStream out = new PipedOutputStream();
//创建读取流
PipedInputStream in = new PipedInputStream();
//为写入和读取建立连接
out.connect(in);
//创建写入流线程
Thread outThread = new Thread(new PipedThreadOut(out));
//创建读取流线程
Thread inThread = new Thread(new PipedThreadIn(in));
//启动线程
outThread.start();
Thread.sleep(1000);
inThread.start();
}
}
结果:
写入数据为:我是pipedOutputStream流,写入数据了!!!
读取数据为:我是pipedOutputStream流,写入数据了!!!
=====================================
解释一下代码编写的过程
1.首先创建一个输出管道的 runnable
的实现类作为写入数据线程类使用,写入数据需要传入一个输出管道流对象。
2. 在创建一个输入管道的 runnable
的实现类作为读取数据的线程类使用,读取数据需要传入一个输入管道流对象。
3. 在测试类创建一个输出流对象和一个输入流对象。
4. 在创建2个线程将输出和输入对象传到各自对应的 runnable
的实现类中
5. 最后启动2个线程。
注意:一定要将输入和输出流简历连接 connect
字符管道流
字符管道流和字节管道流几乎是一模一样的使用,只需要将输入字节流修改成字符流,以及将输出字节流修改为输出字符流,并且需要将读取缓冲区的 byte
数组修改为 char
数组即可。直接看代码吧!!!
/**
* 写入线程
*/
public class PipedThreadOut implements Runnable {
/**
* 管道输出流
*/
private PipedWriter out;
/**
* 构造函数
* @param out
*/
public PipedThreadOut(PipedWriter out) {
this.out = out;
}
/**
* 写入数据
*/
private void write() {
String data = "我是pipedWrite流,写入数据了!!!";
try {
this.out.write(data);
System.out.println("写入数据为:"+data);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
this.out.close();//关闭输出流
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
//开始写入
this.write();
}
}
/**
* 读取线程
*/
class PipedThreadIn implements Runnable {
/**
* 管道输出流
*/
private PipedReader in;
/**
* 构造函数
* @param in
*/
public PipedThreadIn(PipedReader in) {
this.in = in;
}
/**
* 读取数据
*/
private void read() {
//定义一个缓冲区
char[] b = new char[1024];
//记录读取字节数
int len;
String data = "";
try {
//开始读取
while ((len = this.in.read(b)) > 0) {
data += new String(b,0,len);
}
System.out.println("读取数据为:" + data);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
this.in.close();//关闭读取流
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("=====================================");
}
@Override
public void run() {
//开始读取
this.read();
}
}
//测试运行代码
public class PipedThreadTest {
public static void main(String[] args) throws IOException, InterruptedException {
//创建写入流
PipedWriter out = new PipedWriter();
//创建读取流
PipedReader in = new PipedReader();
//为写入和读取建立连接
out.connect(in);
//创建写入流线程
Thread outThread = new Thread(new PipedThreadOut(out));
//创建读取流线程
Thread inThread = new Thread(new PipedThreadIn(in));
//启动线程
outThread.start();
Thread.sleep(1000);
inThread.start();
}
}
//运行结果:
写入数据为:我是pipedWrite流,写入数据了!!!
读取数据为:我是pipedWrite流,写入数据了!!!
=====================================
好了管道流比较简单,和前面学习的流差不多,只是配合线程使用了一下。
写完了如果写得有什么问题,希望读者能够给小编留言,也可以点击[此处扫下面二维码关注微信公众号](https://www.ycbbs.vip/?p=28 "此处扫下面二维码关注微信公众号")
看完两件小事
如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:
- 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
- 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
本文著作权归作者所有,如若转载,请注明出处
转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com