java.io源碼解析(五)--管道字節(jié)流(PipedInputStream苇经,PipedOutputStream)管道字符流(PipedReader,PipedWriter)

聲明:本系列只供本人自學使用宦言,勿噴扇单。

參考:https://www.cnblogs.com/skywang12345/p/io_04.html

管道流一般用于線程間的通訊。

大致流程:在線程A中向PipedOutputStream中寫入數據奠旺,這些數據會自動的發(fā)送到與PipedOutputStream對應的PipedInputStream中蜘澜,進而存儲在PipedInputStream的緩沖中施流;此時,線程B通過讀取PipedInputStream中的數據鄙信,就可以實現瞪醋,線程A和線程B的通信。

一扮碧、PipedInputStream

public class PipedInputStream extends InputStream{
    // 循環(huán)緩存數組趟章,默認1024
    protected byte buffer[];
    // PipedOutputStream往PipedInputStream的buffer中寫入數據的下一個位置
    protected int in = -1;
    // PipedInputStream從buffer中讀數據的下一個位置
    protected int out = 0;
}
  • 構造器
    // 使得 PipedOutputStream與該PipedInputStream建立連接
    public PipedInputStream(PipedOutputStream src) throws IOException {
        this(src, DEFAULT_PIPE_SIZE);
    }

    public PipedInputStream(PipedOutputStream src, int pipeSize) throws IOException {
         initPipe(pipeSize);
         connect(src);
    }

    // 構造未建立連接的PipedInputStream
    public PipedInputStream()
    public PipedInputStream(int pipeSize)

-核心方法

    // 建立連接
    public void connect(PipedOutputStream src) throws IOException {
        src.connect(this);
    }

    // 是PipedOutputStream的write(int b)方法中調用的,使得PipedInputStream能receive
    protected synchronized void receive(int b) throws IOException{
        1.檢查連接狀態(tài)慎王,checkStateForReceive();
        2.假如寫入的所有數據已全部讀完(即in==out)蚓土,awaitSpace();
          將新寫入的數據添加到buffer中
    }
    
    // 若 “寫入管道” 已將 “讀取管道” 的緩存buffer寫滿,則需要執(zhí)行awaitSpace()操作
    // 喚醒“讀取管道”的線程進行讀壤涤佟(讀完即可清空buffer繼續(xù)寫入)
    private void awaitSpace() throws IOException {
        while (in == out) {
            checkStateForReceive();

            notifyAll();
            try {
                wait(1000);
            } catch (InterruptedException ex) {
                throw new java.io.InterruptedIOException();
            }
        }
    }

    // 接收byte[]數組
    // 在PipedOutputStream的write(byte b[], int off, int len)方法中調用蜀漆,使得PipedInputStream能receive
    synchronized void receive(byte b[], int off, int len)  throws IOException{
        checkStateForReceive();
        writeSide = Thread.currentThread();//獲取寫入線程
        int bytesToTransfer = len;//PipedOutputStream寫入的字節(jié)總數
        while (bytesToTransfer > 0) {
            // 第一次執(zhí)行時,in=-1,out=0咱旱,證明buffer為空
            if (in == out)
                awaitSpace();

            // 計算可拷貝到buffer的字節(jié)總數 nextTransferAmount 
            int nextTransferAmount = 0;
            if (out < in) {
                nextTransferAmount = buffer.length - in;
            } else if (in < out) {
                if (in == -1) {
                    in = out = 0;
                    nextTransferAmount = buffer.length - in;
                } else {
                    nextTransferAmount = out - in;
                }
            }
            if (nextTransferAmount > bytesToTransfer)
                nextTransferAmount = bytesToTransfer;
            assert(nextTransferAmount > 0);

            // 拷貝到buffer
            System.arraycopy(b, off, buffer, in, nextTransferAmount);
            bytesToTransfer -= nextTransferAmount;
            off += nextTransferAmount;
            in += nextTransferAmount;
            // 已經寫入1024個字節(jié)后(即buffer已滿)确丢,需要將循環(huán)數組in歸0
            if (in >= buffer.length) {
                in = 0;
            }
        }
}

    // 返回下一個字節(jié)
    public synchronized int read()  throws IOException
    // 將buffer的數據讀取到 byte b[],當都讀完后吐限,清空buffer(即 int=-1,out=0)
    public synchronized int read(byte b[], int off, int len)  throws IOException 

二鲜侥、PipedOutputStream

public class PipedOutputStream extends OutputStream{
    private PipedInputStream sink;
}
  • 構造器
    // 與PipedInputStream建立連接
    public PipedOutputStream(PipedInputStream snk)  throws IOException {
        connect(snk);
    }

    // 構造未建立連接的PipedOutputStream
    public PipedOutputStream() {
    }

-核心方法

    // 建立連接
    public synchronized void connect(PipedInputStream snk) throws IOException

    public void write(int b)  throws IOException{
        sink.receive(b);
    }

    public void write(byte b[], int off, int len) throws IOException{
        sink.receive(b, off, len);
    }
    
    // 清空PipedOutputStream
    // 目的是讓“管道輸入流”放棄對當前資源的占有,讓其它的等待線程(等待讀取管道輸出流的線程)讀取“管道輸出流”的值诸典。
    public synchronized void flush() throws IOException {
        if (sink != null) {
            synchronized (sink) {
                sink.notifyAll();
            }
        }
    }
    
    // 關閉PipedOutputStream并釋放資源
    public void close()  throws IOException {
        if (sink != null) {
            sink.receivedLast();
        }
    }

三描函、demo

public class Test3 {
    public static void main(String[] args) throws IOException {
        Sender sender = new Sender();
        Receiver receiver = new Receiver();
        receiver.getPipedInputStream().connect(sender.getPipedOutputStream());
        sender.start();
        receiver.start();
    }
}

class Sender extends Thread {
    private PipedOutputStream pipedOutputStream = new PipedOutputStream();

    public PipedOutputStream getPipedOutputStream() {
        return pipedOutputStream;
    }

    @Override
    public void run() {
        writeMessage();
    }

    private void writeMessage() {
        try {
            pipedOutputStream.write("哈嘍,China".getBytes());
            pipedOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class Receiver extends Thread {
    private PipedInputStream pipedInputStream = new PipedInputStream();

    public PipedInputStream getPipedInputStream() {
        return pipedInputStream;
    }

    @Override
    public void run() {
        readMessage();
    }

    void readMessage() {
        try {
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = pipedInputStream.read(bytes)) != -1) {
                System.out.println(new String(bytes, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末狐粱,一起剝皮案震驚了整個濱河市舀寓,隨后出現的幾起案子,更是在濱河造成了極大的恐慌肌蜻,老刑警劉巖互墓,帶你破解...
    沈念sama閱讀 221,406評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異蒋搜,居然都是意外死亡篡撵,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,395評論 3 398
  • 文/潘曉璐 我一進店門豆挽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酸休,“玉大人,你說我怎么就攤上這事祷杈“咚荆” “怎么了?”我有些...
    開封第一講書人閱讀 167,815評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宿刮。 經常有香客問我互站,道長,這世上最難降的妖魔是什么僵缺? 我笑而不...
    開封第一講書人閱讀 59,537評論 1 296
  • 正文 為了忘掉前任胡桃,我火速辦了婚禮,結果婚禮上磕潮,老公的妹妹穿的比我還像新娘翠胰。我一直安慰自己,他們只是感情好自脯,可當我...
    茶點故事閱讀 68,536評論 6 397
  • 文/花漫 我一把揭開白布之景。 她就那樣靜靜地躺著,像睡著了一般膏潮。 火紅的嫁衣襯著肌膚如雪锻狗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,184評論 1 308
  • 那天焕参,我揣著相機與錄音轻纪,去河邊找鬼。 笑死叠纷,一個胖子當著我的面吹牛刻帚,可吹牛的內容都是我干的。 我是一名探鬼主播涩嚣,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼崇众,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了缓艳?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,668評論 0 276
  • 序言:老撾萬榮一對情侶失蹤看峻,失蹤者是張志新(化名)和其女友劉穎阶淘,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體互妓,經...
    沈念sama閱讀 46,212評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡溪窒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,299評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了冯勉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澈蚌。...
    茶點故事閱讀 40,438評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖灼狰,靈堂內的尸體忽然破棺而出宛瞄,到底是詐尸還是另有隱情,我是刑警寧澤交胚,帶...
    沈念sama閱讀 36,128評論 5 349
  • 正文 年R本政府宣布份汗,位于F島的核電站盈电,受9級特大地震影響,放射性物質發(fā)生泄漏杯活。R本人自食惡果不足惜匆帚,卻給世界環(huán)境...
    茶點故事閱讀 41,807評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望旁钧。 院中可真熱鬧吸重,春花似錦、人聲如沸歪今。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,279評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彤委。三九已至鞭铆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間焦影,已是汗流浹背车遂。 一陣腳步聲響...
    開封第一講書人閱讀 33,395評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斯辰,地道東北人舶担。 一個月前我還...
    沈念sama閱讀 48,827評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像彬呻,于是被迫代替她去往敵國和親衣陶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,446評論 2 359

推薦閱讀更多精彩內容

  • 概述 管道流是用來在多個線程之間進行信息傳遞的Java流闸氮。管道流分為字節(jié)流管道流和字符管道流剪况。字節(jié)管道流:Pipe...
    jijs閱讀 7,962評論 0 3
  • layout: posttitle: 《Java并發(fā)編程的藝術》筆記categories: Javaexcerpt...
    xiaogmail閱讀 5,831評論 1 19
  • 1.import static是Java 5增加的功能,就是將Import類中的靜態(tài)方法,可以作為本類的靜態(tài)方法來...
    XLsn0w閱讀 1,233評論 0 2
  • 本部分總結一下JAVA IO的相關知識蒲跨。 全部章節(jié)傳送門: JAVA IO學習筆記: IO基本知識 JAVA IO...
    簡單一點點閱讀 1,909評論 0 0
  • 專業(yè)考題類型管理運行工作負責人一般作業(yè)考題內容選項A選項B選項C選項D選項E選項F正確答案 變電單選GYSZ本規(guī)程...
    小白兔去釣魚閱讀 9,007評論 0 13