Java 中利用管道实现线程间的通讯

Python016

Java 中利用管道实现线程间的通讯,第1张

在Java 语言中 提供了各种各样的输入输出流(stream) 使我们能够很方便的对数据进行操作 其中 管道(pipe)流是一种特殊的流 用于在不同线程(threads)间直接传送数据 一个线程发送数据到输出管道 另一个线程从输入管道中读数据 通过使用管道 实现不同线程间的通讯 无需求助于类似临时文件之类的东西 本文在简要介绍管道的基本概念后 将以一个具体的实例pipeapp加以详细说明 .管道的创建与使用Java提供了两个特殊的专门的类专门用于处理管道 它们就是pipedinputstream类和pipeoutputstream类 Pipedinputstream代表了数据在管道中的输出端 也就是线程向管道读数据的一端 pipeoutputstream代表了数据在管道中的输入端 也就是线程向管道写数据的一端 这两个类一起使用可以提供数据的管道流 为了创建一个管道流 我们必须首先创建一个pipeoutstream对象 然后 创建pipeinputstream对象 实例如下 pipeout= new pipedyoutstream()pipein= new pipedputsteam(pipepout)一旦创建了一个管道后 就可以象操作文件一样对管道进行数据的读写 .演示程序 pipeapp应用程序由三个程序组成 主线程(pipeapp Java)及由主线程启动的两个二级线程(ythread Java和zthread Java) 它们使用管道来处理数据 程序从一个内容为一行一行 x 字母的 input txt 文件中读取数据 使用管道传输数据 第一次是利用线程ythread将数据 x 转换为 y 最后利用线程zthread将 y 转换为 z 之后 程序在屏幕上显示修改后的数据 主线程 (pipeapp Java)在main()方法中 程序首先创建一个应用对象 pipeapp pipeapp=new pipeapp()由于程序中流操作都需要使用IOException异常处理 所以设置了一个try块 在try中 为了从源文件中读取数据 程序为 input txt 文件创建了一个输入流Xfileln :fileinputstream xfileln= new fileinputstream( input txt )新的输入流传递给changetoy()方法 让线程ythread能读取该文件 inputstream ylnpipe =pipeapp changetoy(xfileln)changetoy()方法创建将输入数据 x 改变到 y 的线程ythread 并返回该线程的输入管道 inputstream zlnpipe = pipeapp changetoz(ylnpipe)changetoz()方法启动将数据从 y 改变到 z 的线程zehread 主程序将使用从changetoz()返回的输入管道 得到以修改的数据 然后 程序将管道输入流定位到datainputstream对象 使程序能够使用readline()方法读取数据 datainputstream inputstream = new datainputstream(zlnpiepe)创建了输入流以后 程序就可以以行一行的读取数据病显示在屏幕上 String str= inputstream readline()While(str!=null){system out println(str) str=inputstream readline()} 显示完成之后 程序关闭输入流 inputstream close()changetoy()方法 changetoy()方法首先通过传递一个参数inputstream给datainputstream对象来定位资源的输入流 使程序能使用readline()方法从流中读取数据 datainputstream xfileln =new datainutstream(inputstream) 然后 changetoy()创建输出管道和输入管道 pipeoutstream pipeout = new pipeoutputstream()pipeinputstream pipeln = new pipedinputsteam(pipeout)为了能够使用println()方法输出修改的后的文本行到管道 程序将输出管道定位到printstream对象 printstream printstream = new printstream(pipeout)现在 程序可以创建将数据从x改变到y的线程 该线程是ythread类的一个对象 他传递两个参数 输入文件(xfileln)和输出管道(调用printstream) ythread ythread =new thread(xfileln printstream)之后 程序启动线程 changetoz()方法changetoz()方法与changetoy()方法很相似 他从changetoy()返回的输入流开始 datainputstream yfileln= new datainputstream(inputstream)程序创建一个新的管道 pipedoutstream pipeout = new pipedoutputstream()pipedinputstream pipeln = new pipedinputsream(pipeout )该线程通过这个新的管道发出修改后的数据(输入流pipeln )给主程序 源程序如下 ////pipeapp Java pipeapp的主应用程序//import Java io *class pipeapp{public static void main(string[] args){pipeapp pipeapp=new pipeapp()try{fileinputstream xfile =new fileinputstream( input txt )inputstream ylnpipe = pipeapp changetoy(xfileln)inputstream zlnpipe=pipeapp changetoz(ylnpipe)system out println()system out println( here are the results )system out pringln()datainputstream inputstream = nes datainputstream(zlnpipe)string str = inputstream readline()while (str!=null){system out println(str)str=inputstream readline()}inputstream close()}catch(exception e){system out println(e tostring())}}public inputstream changetoy(inputstream inputstream){try{datainputstream pipeout = new datainputsteam(inputstream)pipedoutstream pipeout = new pipedoutputstream()pipedlnsteam pipeln = new pipedlnputstream(pipeout)printstream printstream = new printstream(pipeout)ythread ythread = new ythread(xfileln printstream)ythread start()return pipeln}catch(exeption e){system out println(x tostring())}return null}public inputstream changetoz(inputstream inputsteam){try{datainputstream yfileln = new datainputstream(inputstream)pipeoutputstream pipeln = new pipedinputstream(pipeout )printrstream printstream = new printsteam(pipeout )zthread zthread = new zthread(yfileln printstream )zthread start()return pipeln }catch(exception e){system out println(e tostring())}return null}} Ythread类和Zthread类由于ythread类与zthread类基本一样 在此仅以ythread为例加以说明 Ythread的构造器接收两个参数 输入的文件和第一个管道的输出端 构造器存储这两个参数作为类的数据成员  Ythread(datainputstream xfileln pringstream printstream){this xfileln = xfilelnthis printstream = printstream} 线程通过run()方法来处理数据 首先读取一行数据 确保xstring不为空的情况下循环执行 string xstring = xfileln readline()每读一行数据 完成一次转换string ystring = xstring replace( x y )然后将修改后的数据输出到管道的输出端 prinstream prinrln(ystring)为了确保所有缓冲区的数据完全进入管道的输出端 pringstram flush()循环完成后 线程关闭管道输出流  pringstram close()ythread类的源程序如下 //ythread Java//import Java io *class ythread exteads thread{datainputstream xfilelnpringstream printstreamythread(datainputstream xfileln pringstream printstream){this xfileln = xfilelnthis printstream = printstream}public void run(){try{string xstring = xfileln readline()while(xstring!=null){string ystring= xstring replace( x y )printstream pringln(ystring)printstream flush()xstring= xfileln readline()}printstream close()}catch{ioexception e}{system out println(e tostring())}}} pipeapp应用程序使用microsoft visual j++ 编译 lishixinzhi/Article/program/Java/gj/201311/27508

管道流实际上就是整行的读取和写入,不用每个字节每个字节的读取和写入

读写是两个不同的分支,通常都是分开单独使用的。

可以通过BufferedReader 流的形式进行流缓存,之后通过readLine方法获取到缓存的内容。

BufferedReader bre = null

try {

String file = "D:/test/test.txt"

bre = new BufferedReader(new FileReader(file))//此时获取到的bre就是整个文件的缓存流

while ((str = bre.readLine())!= null) // 判断最后一行不存在,为空结束循环

{

System.out.println(str)//原样输出读到的内容

};

备注一: 流用完之后必须close掉,如上面的就应该是:bre.close(),否则bre流会一直存在,直到程序运行结束。

可以通过“FileOutputStream”创建文件实例,之后过“OutputStreamWriter”流的形式进行存储,举例:

OutputStreamWriter pw = null//定义一个流

pw = new OutputStreamWriter(new FileOutputStream(“D:/test.txt”),"GBK")//确认流的输出文件和编码格式,此过程创建了“test.txt”实例

pw.write("我是要写入到记事本文件的内容")//将要写入文件的内容,可以多次write

pw.close()//关闭流

备注二:文件流用完之后必须及时通过close方法关闭,否则会一直处于打开状态,直至程序停止,增加系统负担。