在Java语言中提供了各种各样的输入/输出流Stream,使我们能够方便地对数据进行操作,其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据。一个发送数据到输出管道,另一个线程从输入管道中读数据。通过使用管道,实现不同线程间的通信,而无需借助于临时文件之类的动西。

  在Java的JDK中提供了4个类来使线程间可以通信:

  (1)PipedInputStream和PipedOutputStream

  (2)PipedReader和PipedWriter

1. 通过字节流 Stream实现线程间通信

用 PipedInputStream和PipedOutputStream实现线程间通信:

package cn.qlq.thread.eight;import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import sun.misc.IOUtils;/*** 通过管道进行线程间通信:字节流* * @author Administrator**/
public class Demo1 {private static final Logger LOGGER = LoggerFactory.getLogger(Demo1.class);public static void main(String[] args) throws IOException {final PipedInputStream inputStream = new PipedInputStream();final PipedOutputStream outputStream = new PipedOutputStream();// 使管道建立连接// inputStream.connect(outputStream);
        outputStream.connect(inputStream);// 开启线程读和写入new Thread(new Runnable() {@Overridepublic void run() {LOGGER.info("threamName ->{} 进入run ", Thread.currentThread().getName());try {for (int i = 0; i < 10; i++) {String data = String.valueOf(i);outputStream.write(data.getBytes());LOGGER.info("threadName->{} write data ->{}", Thread.currentThread().getName(), data);outputStream.flush();}outputStream.close();LOGGER.info("threamName ->{} 结束run ", Thread.currentThread().getName());} catch (IOException e) {e.printStackTrace();}}}, "writeThread").start();new Thread(new Runnable() {@Overridepublic void run() {try {LOGGER.info("threamName ->{} 进入run ", Thread.currentThread().getName());byte[] buffer = new byte[20];int readLength = inputStream.read(buffer);while (readLength != -1) {String data = new String(buffer, 0, readLength);LOGGER.info("threadName->{} read data ->{}", Thread.currentThread().getName(), data);readLength = inputStream.read(buffer);}inputStream.close();LOGGER.info("threamName ->{} 结束run ", Thread.currentThread().getName());} catch (IOException e) {e.printStackTrace();}}}, "readThread").start();}
}

结果:

12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threamName ->readThread 进入run
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threamName ->writeThread 进入run
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->0
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->1
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->0
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->2
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->12
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->3
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->3
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->4
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->4
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->5
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->5
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->6
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->6
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->7
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->7
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->8
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->8
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->writeThread write data ->9
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threadName->readThread read data ->9
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threamName ->writeThread 结束run
12:11:33 [cn.qlq.thread.eight.Demo1]-[INFO] threamName ->readThread 结束run

  使用代码outputStream.connect(inputStream); (或者inputStream.connect(outputStream);)是为了使两个管道建立通信连接,这样才可以将数据进行输入与输出。

  readThread 启动后,由于当时没有数据被写入,所以线程阻塞在int readLength = inputStream.read(buffer);  直到有数据被写入时,才继续向下运行。

2. 通过字符流 Reader\Writer实现线程间通信

  例子与上面一样:

package cn.qlq.thread.eight;import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 通过管道进行线程间通信:字符流* * @author Administrator**/
public class Demo2 {private static final Logger LOGGER = LoggerFactory.getLogger(Demo2.class);public static void main(String[] args) throws IOException {final PipedWriter writer = new PipedWriter();final PipedReader reader = new PipedReader();// 使管道建立连接// writer.connect(reader);
        reader.connect(writer);// 开启线程读和写入new Thread(new Runnable() {@Overridepublic void run() {LOGGER.info("threamName ->{} 进入run ", Thread.currentThread().getName());try {for (int i = 0; i < 5; i++) {String data = String.valueOf(i);writer.write(data);LOGGER.info("threadName->{} write data ->{}", Thread.currentThread().getName(), data);}writer.close();LOGGER.info("threamName ->{} 结束run ", Thread.currentThread().getName());} catch (IOException e) {e.printStackTrace();}}}, "writerThread").start();new Thread(new Runnable() {@Overridepublic void run() {try {LOGGER.info("threamName ->{} 进入run ", Thread.currentThread().getName());char[] buffer = new char[20];int read = reader.read(buffer);while (read != -1) {String data = new String(buffer, 0, read);LOGGER.info("threadName->{} read data ->{}", Thread.currentThread().getName(), data);read = reader.read(buffer);}reader.close();LOGGER.info("threamName ->{} 结束run ", Thread.currentThread().getName());} catch (IOException e) {e.printStackTrace();}}}, "readThread").start();}
}

结果:

13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threamName ->writerThread 进入run
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threamName ->readThread 进入run
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->0
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->0
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->1
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->1
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->2
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->2
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->3
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->3
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->4
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->4
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->5
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->5
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->6
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->6
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->7
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->7
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->8
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->8
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->writerThread write data ->9
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threadName->readThread read data ->9
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threamName ->writerThread 结束run
13:29:52 [cn.qlq.thread.eight.Demo2]-[INFO] threamName ->readThread 结束run

  

  代码    // writer.connect(reader); (或者 reader.connect(writer);) 是使两个管道建立通信连接。

转载于:https://www.cnblogs.com/qlqwjy/p/10118733.html

通过管道进行线程间通信相关推荐

  1. java线程间通信管道_通过管道进行线程间通信

    管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据.一个线程发送数据到输出管道,另一个线程从输入管道中读数据.通过管道,实现不同线程间的通信,而无须借助类似共享变量.临时文件之 ...

  2. NIO详解(十一):线程间通信管道Pipe

    1. 概述 Java NIO 管道是2个线程之间的单向数据连接.Pipe有一个source通道和一个sink通道.数据会被写到sink通道,从source通道读取.下面是Pipe原理的图示: 当有两个 ...

  3. linux线程间通信优点,进程间通信与线程间通信【转】

    一个进程写管道:写入字节数小于PIPE_BUF是原子操作,写操作在管道缓冲区没有及时读走时发生阻塞. 一个进程读管道:读操作在管道缓冲区没有数据时发生阻塞. 以前一直想找个机会总结一下进程和线程的通信 ...

  4. Java多线程编程-(4)-线程间通信机制的介绍与使用

    上一篇: Java多线程编程-(1)-线程安全和锁Synchronized概念 Java多线程编程-(2)-可重入锁以及Synchronized的其他基本特性 Java多线程编程-(3)-线程本地Th ...

  5. Unix/Linux IPC及线程间通信总结

    一.互斥与同步 1.互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性.但互斥无法限制访问者对资源的访问顺序,即访问是无序的. 2.同步:是指在互斥的基础上(大多数情况),通过其它 ...

  6. 进程间通信线程间通信

    一.多进程: 首先,先来讲一下fork之后,发生了什么事情. 由fork创建的新进程被称为子进程(child process).该函数被调用一次,但返回两次.两次返回的区别是子进程的返回值是0,而父进 ...

  7. Java 多线程(六)——进程间通信与线程间通信

    以前一直想找个机会总结一下进程和线程的通信机制,但由于技术和平台的局限性,一直没有找准切入点.由于马上要毕业了,对自己技术的总结和梳理的前提下写了本篇文章,如有错误之处,敬请拍砖和指教. 操作系统的主 ...

  8. java 生产者消费者_Java多线程:线程间通信—生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是, 多个线程之间如何协作呢 ? 我们看一个 ...

  9. 进程间通信和线程间通信

    进程间通信 转自  https://www.cnblogs.com/LUO77/p/5816326.html 线程间通信  https://www.cnblogs.com/jobs1/p/107840 ...

最新文章

  1. base64转码java版
  2. BeeHive模块注册
  3. WdatePicker控件的使用
  4. uva 755 487--3279
  5. GDCM:dicom文件转储签证变更的测试程序
  6. Safari浏览器不支持……
  7. SAP License:从SAP顾问面试看职场
  8. EL表达式、 jstl标签
  9. 计算机基础知识运算符,计算机基础运算符
  10. java 邮件发送 多人_java 发送邮件(可发送多人,抄送多人,可带附件)
  11. c语言程序100例pdf,经典c程序100例源代码(全).pdf
  12. 两个服务器同步网站数据,两个服务器之间数据库同步
  13. 基于VUE接入TinyMCE富文本编辑器 漂亮简洁 封装成组件随用随调
  14. 用汉字能给计算机编程,为什么中国的程序员不能用中文来编程?
  15. 神经网络量化--per-channel量化
  16. 从零开始写高性能的人脸识别服务器(三)
  17. 以麒麟音乐为例,教你如何构建专属自己的音乐播放器
  18. 什么是大小端?如何确定大小端?
  19. Web设计中的中国传统色彩速查表
  20. 微信小程序 - 如何利用百度飞桨实现图像分类识别

热门文章

  1. Android 音频开发(三) 如何播放一帧音频数据上
  2. vue中请求接口怎么封装公共地址_如何修改Vue打包后文件的接口地址配置(转自网络)...
  3. 台达伺服驱动器说明书_干货:伺服调机实例讲解
  4. c++最快简洁提供http文件服务
  5. ffmpeg 2.6.3在Linux下的编译
  6. Linux文件inode用完一例
  7. 【Flink】Flink Failed to push metrics to PushGateway Connect refuse
  8. 【nginx】nginx 反向代理 指令说明
  9. requirement failed: Can only call getServletHandlers on a running MetricsSystem
  10. 【Flink】No key set. This method should not be called outside of a keyed context.