1. 程式人生 > >多執行緒程式設計之執行緒間的通訊——管道通訊

多執行緒程式設計之執行緒間的通訊——管道通訊

上一章節講了wait/notify通訊,這一節我們來探討使用管道進行通訊。
java中提供了IO流使我們很方便的對資料進行操作,pipeStream是一種特殊的流,用於不同執行緒間直接傳送資料。一個執行緒將資料傳送到輸出管道,另一個執行緒從輸入管道讀取資料。通過管道實現通訊不需要藉助臨時檔案這類東西。
java中提供了四個類使得執行緒間可以通訊:
①位元組流:PipeInputStream,PipedOutputStream
②字元流:PipedReader,PipedWriter

下面我們看看位元組流的實現方法:

package pipeInputOutput;
//輸出流
import
java.io.IOException; import java.io.PipedOutputStream; public class WriteDate { public void writeMethod(PipedOutputStream out) { try { System.out.println("write:"); for(int i=0;i<300;i++) { String outDate=""+(i+1); out.write(outDate.getBytes()); System.out.print(outDate); } System.out.println(); out.close(); }catch
(IOException e) { e.printStackTrace(); } } } package pipeInputOutput; //輸入流 import java.io.IOException; import java.io.PipedInputStream; public class ReadDate { public void ReadDate(PipedInputStream input) { try { System.out.println("read:"); byte
[] byteArray=new byte[20]; int readLength=input.read(byteArray); while(readLength!=-1) { String newDate=new String(byteArray,0,readLength); System.out.print(newDate); readLength=input.read(byteArray); } System.out.println(); input.close(); }catch(IOException e){ e.printStackTrace(); } } } package pipeInputOutput; import java.io.PipedOutputStream; //輸出執行緒 public class ThreadWrite extends Thread { private WriteDate write; private PipedOutputStream out; public ThreadWrite(WriteDate write,PipedOutputStream out) { super(); this.write=write; this.out=out; } public void run() { write.writeMethod(out); } } package pipeInputOutput; import java.io.PipedInputStream; //輸入執行緒 public class ThreadRead extends Thread{ private ReadDate read; private PipedInputStream in; public ThreadRead(ReadDate read,PipedInputStream in) { super(); this.read=read; this.in=in; } public void run() { read.ReadDate(in); } } package pipeInputOutput; import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; //測試方法 public class Run { public static void main(String[] args) { try { WriteDate write=new WriteDate(); ReadDate read=new ReadDate(); PipedInputStream inputStream=new PipedInputStream(); PipedOutputStream outputStream=new PipedOutputStream(); //輸出流與輸入流進行連線。 outputStream.connect(inputStream); //inputStream.connect(outputStream); ThreadRead readThread=new ThreadRead(read,inputStream); readThread.start();//先啟動輸出執行緒 Thread.sleep(2000); ThreadWrite writeThread=new ThreadWrite(write,outputStream); writeThread.start();//後啟動輸入執行緒 } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } 控制檯輸出: read: write: 123456789101112131415161718192021... 123456789101112131415161718192021...

上面測試中,先啟動輸入執行緒,然後因為沒有執行緒被寫入所以執行緒被阻塞,知道有資料寫入。

我們接著繼續看看字元流的實現方法:

package pipeInputOutput1;
import java.io.IOException;
import java.io.PipedWriter;
//字元輸出流
public class WriteDate {
    public void writeMethod(PipedWriter out) {
        try {
            System.out.println("write:");
            for(int i=0;i<300;i++) {
                String outDate=""+(i+1);
                out.write(outDate);
                System.out.print(outDate);
            }
            System.out.println();
            out.close();
        }catch(IOException e) {
            e.printStackTrace();

        }
    }

}


package pipeInputOutput1;
import java.io.IOException;
import java.io.PipedReader;
//字元輸入流
public class ReadDate {
    public void readMethod(PipedReader in) {

        try {
            System.out.println("read:");
            char[] byteArray=new char[20];
            int readLength=in.read(byteArray);
            while(readLength!=-1) {
                String newDate=new String(byteArray,0,readLength);
                System.out.print(newDate);
                readLength=in.read(byteArray);
            }
            System.out.println();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

package pipeInputOutput1;
import java.io.PipedWriter;
//輸出流執行緒
public class WriteThread extends Thread {
    private WriteDate write;
    private PipedWriter out;
    public WriteThread(WriteDate write,PipedWriter out) {
        super();
        this.write=write;
        this.out=out;
    }

    public void run() {
        write.writeMethod(out);
    }

}


package pipeInputOutput1;
import java.io.PipedReader;
//輸入流執行緒
public class ReadThread extends Thread{
    private ReadDate read;
    private PipedReader in;
    public ReadThread(ReadDate read,PipedReader in) {
        super();
        this.read=read;
        this.in=in;
    }
    public void run() {
        read.readMethod(in);
    }

}


package pipeInputOutput1;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
//測試方法
public class run {
    public static void main(String[] args) {
        try {
            WriteDate write=new WriteDate();
            ReadDate read=new ReadDate();

            PipedWriter out=new PipedWriter();
            PipedReader in=new PipedReader();
            //連線輸出流與輸入流
            out.connect(in);
            //in.connect(out);
            ReadThread threadread=new ReadThread(read,in);
            threadread.start();

            Thread.sleep(2000);
            WriteThread threadwrite=new WriteThread(write,out);
            threadwrite.start();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

字元流額位元組流大同小異,上面的例子中字元流不需要建立位元組陣列而已。