并發(fā)編程線程通信之管道流

前言

在并發(fā)編程中,需要處理兩個問題:線程之間如何通信及線程之間如何同步。通知是指線程之間以何種機制來交換信息。在命令式編程中,線程之間的通信機制有兩種:共享內(nèi)存和消息傳遞

在共享內(nèi)存的并發(fā)模型里,線程之間共享程序的公共狀態(tài),通過寫-讀內(nèi)存中的公共狀態(tài)進行隱式通信。而子啊消息傳遞的并發(fā)模型里,線程之間沒有公共狀態(tài),線程之間必須通過發(fā)送消息來顯式進行通信。

Java 的并發(fā)才作用的是共享內(nèi)存模型,Java線程之間的通信總是隱式進行,整個通信過程對程序員完全透明。

而Java中還有另一種用的比較少的線程間的通信方式:管道流。

如何使用?

管道輸入/輸入流和普通的文件輸入/輸出流或者網(wǎng)絡(luò)輸入/輸出流不同之處在于,它主要用于線程之間的數(shù)據(jù)傳輸,而傳輸?shù)拿浇闉閮?nèi)存。

管道輸入/輸入流主要包括了如下4種具體實現(xiàn):PipedOutputStream,PipedInputStream,PipedReader 和 PipedWriter,前兩種面向字節(jié),而后兩種面向字符。

我們先來一個例子看看:

public class PipedStreamDemo {

  public static void main(String[] args) throws IOException {
    PipedWriter writer = new PipedWriter();
    PipedReader reader = new PipedReader();
    PipedInputStream inputStream = new PipedInputStream();
    PipedOutputStream outputStream = new PipedOutputStream();

    // 將輸出流和輸入流連接
    writer.connect(reader);
    Thread printThread = new Thread(new Print(reader));

    printThread.start();

    int receive;

    try {
      while ((receive = System.in.read()) != -1) {
        // 從main線程寫到 print 線程
        writer.write(receive);
      }
    } finally {
      writer.close();
    }


  }

  static class Print implements Runnable {

    private PipedReader in;

    public Print(PipedReader in) {
      this.in = in;
    }

    @Override
    public void run() {
      int receive;

      try {
        while ((receive = in.read()) != -1) {
          // 讀取 main 線程發(fā)送過來的數(shù)據(jù)并打印
          System.out.print((char) receive);
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }


}

上面的代碼種,創(chuàng)建了 printThread,它用來接受 main 線程的輸入,任何 main 線程的輸入均通過 PipedWriter 寫入,而 printThread 在另一端通過 PipedReader 將內(nèi)容讀出并打印。

對于 Piped 類型的流,必須先要進行綁定,也就是調(diào)用 connect 方法,如果沒有將輸入 / 輸出流綁定起來,對于該流的訪問將會拋出異常。

而作為這兩個類連接的重要方法 connect 方法式如何實現(xiàn)的呢?

    public synchronized void connect(PipedReader snk) throws IOException {
        if (snk == null) {
            throw new NullPointerException();
        } else if (sink != null || snk.connected) {
            throw new IOException("Already connected");
        } else if (snk.closedByReader || closed) {
            throw new IOException("Pipe closed");
        }

        sink = snk;
        snk.in = -1;
        snk.out = 0;
        snk.connected = true;
    }

首先參數(shù)判斷,然后將輸入流設(shè)置為輸出流的 sink 屬性。這樣就將兩個流關(guān)聯(lián)了起來。實現(xiàn)了兩個線程的通信。

總結(jié)

總的來說,該類的應(yīng)用場景并不是很多,只是我們應(yīng)該知道另一種線程通信的方式。嗯,就醬。

good luck ?。。。?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容