Java中利用管道實現執行緒間的通訊(轉)

ba發表於2007-08-15
Java中利用管道實現執行緒間的通訊(轉)[@more@]在java 語言中,提供了各種各樣的輸入輸出流(stream),使我們能夠很方便的對資料進行操作,其中,管道(pipe)流是一種特殊的流,用於在不同執行緒(threads)間直接傳送資料。一個執行緒傳送資料到輸出管道,另一個執行緒從輸入管道中讀資料。透過使用管道,實現不同執行緒間的通訊。無需求助於類似臨時檔案之類的東西。本文在簡要介紹管道的基本概念後,將以一個具體的例項pipeapp加以詳細說明。

1. 管道的建立與使用
  java提供了兩個特殊的專門的類專門用於處理管道,它們就是pipedinputstream類和pipeoutputstream類。
Pipedinputstream代表了資料在管道中的輸出端,也就是執行緒向管道讀資料的一端;pipeoutputstream代表了資料在管道中的輸入端,也就是執行緒向管道寫資料的一端,這兩個類一起使用可以提供資料的管道流。
  為了建立一個管道流,我們必須首先建立一個pipeoutstream物件,然後,建立pipeinputstream物件,例項如下:
  pipeout= new pipedyoutstream();
  pipein= new pipedputsteam(pipepout);
  一旦建立了一個管道後,就可以象操作檔案一樣對管道進行資料的讀寫。

2. 演示程式: 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 pipeout2 = new pipedoutputstream();
  pipedinputstream pipeln2 = new pipedinputsream(pipeout2);
  該執行緒透過這個新的管道發出修改後的資料(輸入流pipeln2)給主程式。

源程式如下:
//
//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 pipeln2 = new pipedinputstream(pipeout2);
printrstream printstream2 = new printsteam(pipeout2);
zthread zthread = new zthread(yfileln,printstream2);
zthread.start();
return pipeln2;
}
catch(exception e)
{
system.out.println(e.tostring());
}
return null;
}
}

Ythread類和Zthread類
  由於ythread類與zthread類基本一樣,在此僅以ythread為例加以說明。
  Ythread的構造器接收兩個引數:輸入的檔案和第一個管道的輸出端,構造器儲存這兩個引數作為類的資料成員:
  Ythread(datainputstream xfileln,pringstream printstream)
  {
    this.xfileln = xfileln;
    this.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 xfileln;
pringstream printstream;
ythread(datainputstream xfileln,pringstream.printstream)
{
this.xfileln = xfileln;
this.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++1.1編譯

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-958524/,如需轉載,請註明出處,否則將追究法律責任。

相關文章