管道流
- 管道流的主要作用是可以進行兩個線程間的通訊枷遂,分為管道輸出流(
PipedOutputStream
)樱衷、管道輸入流(PipedInputStream
),如果想要進行管道輸出酒唉,則必須要把輸出流連在輸入流之上矩桂,在PipedOutputStream類上有如下的一個方法用于連接管道:
public void connect(PipedInputStream snk)throws IOException
- 通常是創(chuàng)建兩個單獨的線程來實現(xiàn)通信,如果是單個線程的話容易出現(xiàn)線程堵塞痪伦,因為輸出流最多只能向緩沖區(qū)寫入1024個字節(jié)的數(shù)據(jù)侄榴,如果超出就會出現(xiàn)線程堵塞,因此必須創(chuàng)建多個線程實現(xiàn)緩沖區(qū)的釋放和存儲
PipedOutputStream
- 管道輸出流是管道的發(fā)送端网沾,可以將管道輸出流連接到管道輸入流來創(chuàng)建一個通信管道癞蚕,通常,數(shù)據(jù)由某個線程寫入
PipedOutputStream
對象辉哥,并由其他線程從連接的PipedInputStream
讀取涣达。不建議對這兩個對象嘗試使用單個線程,因為這樣可能會造成該線程死鎖证薇。如果某個線程正從連接的管道輸入流中讀取數(shù)據(jù)字節(jié),但該線程不再處于活動狀態(tài)匆篓,則該管道被視為處于 毀壞 狀態(tài)浑度。
構造函數(shù)
PipedOutputStream()
創(chuàng)建尚未連接到管道輸入流的管道輸出流。PipedOutputStream(PipedInputStream snk)
創(chuàng)建連接到指定管道輸入流的管道輸出流鸦概。
常用函數(shù)
close()
關閉void connect(PipedInputStream snk)
將此管道輸出流連接到接收者箩张。void flush()
刷新此輸出流并強制寫出所有緩沖的輸出字節(jié)。void write(byte[] b, int off, int len)
將len
字節(jié)從初始偏移量為off
的指定byte
數(shù)組寫入該管道輸出流窗市。void write(int b)
將指定byte
寫入傳送的輸出流先慷。
PipedInputStream
- 管道輸入流應該連接到管道輸出流;管道輸入流提供要寫入管道輸出流的所有數(shù)據(jù)字節(jié)咨察。通常论熙,數(shù)據(jù)由某個線程從
PipedInputStream
對象讀取,并由其他線程將其寫入到相應的PipedOutputStream
摄狱。不建議對這兩個對象嘗試使用單個線程脓诡,因為這樣可能死鎖線程无午。管道輸入流包含一個緩沖區(qū),可在緩沖區(qū)限定的范圍內將讀操作和寫操作分離開祝谚。 如果向連接管道輸出流提供數(shù)據(jù)字節(jié)的線程不再存在宪迟,則認為該管道已損壞。
構造函數(shù)
PipedInputStream()
創(chuàng)建尚未連接的PipedInputStream
交惯。PipedInputStream(PipedOutputStream src)
創(chuàng)建PipedInputStream
次泽,使其連接到管道輸出流src
。
常用函數(shù)
int available()
返回可以不受阻塞地從此輸入流中讀取的字節(jié)數(shù)席爽。void close()
關閉此管道輸入流并釋放與該流相關的所有系統(tǒng)資源意荤。void connect(PipedOutputStream src)
使此管道輸入流連接到管道輸出流src
。int read()
讀取此管道輸入流中的下一個數(shù)據(jù)字節(jié)拳昌。int read(byte[] b, int off, int len)
將最多len
個數(shù)據(jù)字節(jié)從此管道輸入流讀入byte
數(shù)組袭异。protected void receive(int b)
接收數(shù)據(jù)字節(jié)。
實例
package IO;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/**
* Created by chenjiabing on 17-5-25.
*/
/**
* 注意的問題:
* 1.寫線程正在往緩沖區(qū)寫數(shù)據(jù)的時候炬藤,但是此時的讀線程的管道結束御铃,那么此時的寫線程的管道就會發(fā)生IOException異常
* 2.讀線程正在從緩沖區(qū)讀數(shù)據(jù)的時候,但是此時的寫線程的管道已經結束了沈矿,此時就會引起讀線程的管道發(fā)生IOException異常
* 3.必須是啟用多線程才能實現(xiàn)管道之間的讀寫上真,否則會出現(xiàn)堵塞現(xiàn)象,因為這里的PipeOutputStream每次向緩沖區(qū)寫入的字節(jié)數(shù)最大是1024羹膳,如果不及時的減少緩沖區(qū)的數(shù)據(jù)量就會出現(xiàn)堵塞
*/
public class demo7 {
public static PipedOutputStream outputStream = new PipedOutputStream();
public static PipedInputStream inputStream = new PipedInputStream();
/**
* 創(chuàng)建一個寫入數(shù)據(jù)進程睡互,使用的是PipeOutStream,將數(shù)據(jù)寫入管道中
*/
public static void send() {
new Thread(new Runnable() {
@Override
public void run() {
byte[] bytes = new byte[2000]; //創(chuàng)建一個2000字節(jié)的數(shù)組
while (true) {
try {
outputStream.write(bytes, 0, 2000); //寫入管道陵像,但是這里的緩沖區(qū)最多寫入1024個字節(jié)的數(shù)據(jù)就珠,因此這個是一次沒有寫完
System.out.println("寫入成功");
} catch (IOException e) {
System.out.println("寫入失敗");
System.exit(1);
}
}
}
}).start();
}
/**
* 使用PipeInputStream創(chuàng)建一個讀取的線程
*/
public static void receive() {
new Thread(new Runnable() {
@Override
public void run() {
byte[] bytes = new byte[100]; //一次性只讀取100個字節(jié)
int len = 0;
try {
len = inputStream.read(bytes, 0, 100); //讀取
while (len != -1) {
System.out.println("已經讀取了" + len + "個字節(jié)");
len = inputStream.read(bytes, 0, 100);
}
} catch (IOException e) {
System.out.println("讀取失敗");
System.exit(1);
}
}
}).start();
}
public static void main(String args[]) {
try {
inputStream.connect(outputStream); //連接
} catch (IOException e) {
System.out.println("連接失敗");
System.exit(1);
}
send();
receive();
}
}
注意:從上面的運行結果可以看出,緩沖區(qū)最多可以寫入
1024
個字節(jié)的數(shù)據(jù)醒颖,所以在緩沖區(qū)滿了之后上面的send
進程就會堵塞等待緩沖區(qū)空閑妻怎,如果recieve
進程不繼續(xù)讀取數(shù)據(jù)了,那么就會一直出現(xiàn)堵塞
問題
- 寫線程正在往緩沖區(qū)寫數(shù)據(jù)的時候泞歉,但是此時的讀線程的結束讀取逼侦,那么此時的寫線程的管道就會發(fā)生
IOException
異常,可以將上面receive
進程中的while(true)
去掉就可以清楚的看出- 讀線程正在從緩沖區(qū)讀數(shù)據(jù)的時候腰耙,但是此時的寫線程的管道已經結束了榛丢,此時就會引起讀線程的管道發(fā)生
IOException
異常,將上面的send
進程中的while(true)
去掉就可以實現(xiàn)這個問題- 必須是啟用多線程才能實現(xiàn)管道之間的讀寫,否則會出現(xiàn)堵塞現(xiàn)象挺庞,因為這里的
PipeOutputStream
每次向緩沖區(qū)寫入的字節(jié)數(shù)最大是1024
晰赞,如果不及時的減少緩沖區(qū)的數(shù)據(jù)量就會出現(xiàn)堵塞
解決方法
- 后續(xù)更新中..........