一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 詳解PipedInputStream和PipedOutputStream_動力節(jié)點Java學(xué)院整理

詳解PipedInputStream和PipedOutputStream_動力節(jié)點Java學(xué)院整理

2020-09-30 15:52動力節(jié)點 Java教程

這篇文章主要為大家詳細(xì)介紹了管道PipedInputStream和PipedOutputStream,具有一定的參考價值,感興趣的小伙伴們可以參考一下

java 管道介紹

在java中,PipedOutputStream和PipedInputStream分別是管道輸出流和管道輸入流。
它們的作用是讓多線程可以通過管道進(jìn)行線程間的通訊。在使用管道通信時,必須將PipedOutputStream和PipedInputStream配套使用。

使用管道通信時,大致的流程是:我們在線程A中向PipedOutputStream中寫入數(shù)據(jù),這些數(shù)據(jù)會自動的發(fā)送到與PipedOutputStream對應(yīng)的PipedInputStream中,進(jìn)而存儲在PipedInputStream的緩沖中;此時,線程B通過讀取PipedInputStream中的數(shù)據(jù)。就可以實現(xiàn),線程A和線程B的通信。
PipedOutputStream和PipedInputStream源碼分析

下面介紹PipedOutputStream和PipedInputStream的源碼。在閱讀它們的源碼之前,建議先看看源碼后面的示例。待理解管道的作用和用法之后,再看源碼,可能更容易理解。

1. PipedOutputStream 源碼分析(基于jdk1.7.40)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package java.io;
 
import java.io.*;
 
public class PipedOutputStream extends OutputStream {
 
  // 與PipedOutputStream通信的PipedInputStream對象
  private PipedInputStream sink;
 
  // 構(gòu)造函數(shù),指定配對的PipedInputStream
  public PipedOutputStream(PipedInputStream snk) throws IOException {
    connect(snk);
  }
 
  // 構(gòu)造函數(shù)
  public PipedOutputStream() {
  }
 
  // 將“管道輸出流” 和 “管道輸入流”連接。
  public synchronized void connect(PipedInputStream snk) throws IOException {
    if (snk == null) {
      throw new NullPointerException();
    } else if (sink != null || snk.connected) {
      throw new IOException("Already connected");
    }
    // 設(shè)置“管道輸入流”
    sink = snk;
    // 初始化“管道輸入流”的讀寫位置
    // int是PipedInputStream中定義的,代表“管道輸入流”的讀寫位置
    snk.in = -1;
    // 初始化“管道輸出流”的讀寫位置。
    // out是PipedInputStream中定義的,代表“管道輸出流”的讀寫位置
    snk.out = 0;
    // 設(shè)置“管道輸入流”和“管道輸出流”為已連接狀態(tài)
    // connected是PipedInputStream中定義的,用于表示“管道輸入流與管道輸出流”是否已經(jīng)連接
    snk.connected = true;
  }
 
  // 將int類型b寫入“管道輸出流”中。
  // 將b寫入“管道輸出流”之后,它會將b傳輸給“管道輸入流”
  public void write(int b) throws IOException {
    if (sink == null) {
      throw new IOException("Pipe not connected");
    }
    sink.receive(b);
  }
 
  // 將字節(jié)數(shù)組b寫入“管道輸出流”中。
  // 將數(shù)組b寫入“管道輸出流”之后,它會將其傳輸給“管道輸入流”
  public void write(byte b[], int off, int len) throws IOException {
    if (sink == null) {
      throw new IOException("Pipe not connected");
    } else if (b == null) {
      throw new NullPointerException();
    } else if ((off < 0) || (off > b.length) || (len < 0) ||
          ((off + len) > b.length) || ((off + len) < 0)) {
      throw new IndexOutOfBoundsException();
    } else if (len == 0) {
      return;
    }
    // “管道輸入流”接收數(shù)據(jù)
    sink.receive(b, off, len);
  }
 
  // 清空“管道輸出流”。
  // 這里會調(diào)用“管道輸入流”的notifyAll();
  // 目的是讓“管道輸入流”放棄對當(dāng)前資源的占有,讓其它的等待線程(等待讀取管道輸出流的線程)讀取“管道輸出流”的值。
  public synchronized void flush() throws IOException {
    if (sink != null) {
      synchronized (sink) {
        sink.notifyAll();
      }
    }
  }
 
  // 關(guān)閉“管道輸出流”。
  // 關(guān)閉之后,會調(diào)用receivedLast()通知“管道輸入流”它已經(jīng)關(guān)閉。
  public void close() throws IOException {
    if (sink != null) {
      sink.receivedLast();
    }
  }
}

2. PipedInputStream 源碼分析(基于jdk1.7.40)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
package java.io;
 
public class PipedInputStream extends InputStream {
  // “管道輸出流”是否關(guān)閉的標(biāo)記
  boolean closedByWriter = false;
  // “管道輸入流”是否關(guān)閉的標(biāo)記
  volatile boolean closedByReader = false;
  // “管道輸入流”與“管道輸出流”是否連接的標(biāo)記
  // 它在PipedOutputStream的connect()連接函數(shù)中被設(shè)置為true
  boolean connected = false;
 
  Thread readSide;  // 讀取“管道”數(shù)據(jù)的線程
  Thread writeSide;  // 向“管道”寫入數(shù)據(jù)的線程
 
  // “管道”的默認(rèn)大小
  private static final int DEFAULT_PIPE_SIZE = 1024;
 
  protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE;
 
  // 緩沖區(qū)
  protected byte buffer[];
 
  //下一個寫入字節(jié)的位置。in==out代表滿,說明“寫入的數(shù)據(jù)”全部被讀取了。
  protected int in = -1;
  //下一個讀取字節(jié)的位置。in==out代表滿,說明“寫入的數(shù)據(jù)”全部被讀取了。
  protected int out = 0;
 
  // 構(gòu)造函數(shù):指定與“管道輸入流”關(guān)聯(lián)的“管道輸出流”
  public PipedInputStream(PipedOutputStream src) throws IOException {
    this(src, DEFAULT_PIPE_SIZE);
  }
 
  // 構(gòu)造函數(shù):指定與“管道輸入流”關(guān)聯(lián)的“管道輸出流”,以及“緩沖區(qū)大小”
  public PipedInputStream(PipedOutputStream src, int pipeSize)
      throws IOException {
     initPipe(pipeSize);
     connect(src);
  }
 
  // 構(gòu)造函數(shù):默認(rèn)緩沖區(qū)大小是1024字節(jié)
  public PipedInputStream() {
    initPipe(DEFAULT_PIPE_SIZE);
  }
 
  // 構(gòu)造函數(shù):指定緩沖區(qū)大小是pipeSize
  public PipedInputStream(int pipeSize) {
    initPipe(pipeSize);
  }
 
  // 初始化“管道”:新建緩沖區(qū)大小
  private void initPipe(int pipeSize) {
     if (pipeSize <= 0) {
      throw new IllegalArgumentException("Pipe Size <= 0");
     }
     buffer = new byte[pipeSize];
  }
 
  // 將“管道輸入流”和“管道輸出流”綁定。
  // 實際上,這里調(diào)用的是PipedOutputStream的connect()函數(shù)
  public void connect(PipedOutputStream src) throws IOException {
    src.connect(this);
  }
 
  // 接收int類型的數(shù)據(jù)b。
  // 它只會在PipedOutputStream的write(int b)中會被調(diào)用
  protected synchronized void receive(int b) throws IOException {
    // 檢查管道狀態(tài)
    checkStateForReceive();
    // 獲取“寫入管道”的線程
    writeSide = Thread.currentThread();
    // 若“寫入管道”的數(shù)據(jù)正好全部被讀取完,則等待。
    if (in == out)
      awaitSpace();
    if (in < 0) {
      in = 0;
      out = 0;
    }
    // 將b保存到緩沖區(qū)
    buffer[in++] = (byte)(b & 0xFF);
    if (in >= buffer.length) {
      in = 0;
    }
  }
 
  // 接收字節(jié)數(shù)組b。
  synchronized void receive(byte b[], int off, int len) throws IOException {
    // 檢查管道狀態(tài)
    checkStateForReceive();
    // 獲取“寫入管道”的線程
    writeSide = Thread.currentThread();
    int bytesToTransfer = len;
    while (bytesToTransfer > 0) {
      // 若“寫入管道”的數(shù)據(jù)正好全部被讀取完,則等待。
      if (in == out)
        awaitSpace();
      int nextTransferAmount = 0;
      // 如果“管道中被讀取的數(shù)據(jù),少于寫入管道的數(shù)據(jù)”;
      // 則設(shè)置nextTransferAmount=“buffer.length - in”
      if (out < in) {
        nextTransferAmount = buffer.length - in;
      } else if (in < out) { // 如果“管道中被讀取的數(shù)據(jù),大于/等于寫入管道的數(shù)據(jù)”,則執(zhí)行后面的操作
        // 若in==-1(即管道的寫入數(shù)據(jù)等于被讀取數(shù)據(jù)),此時nextTransferAmount = buffer.length - in;
        // 否則,nextTransferAmount = out - in;
        if (in == -1) {
          in = out = 0;
          nextTransferAmount = buffer.length - in;
        } else {
          nextTransferAmount = out - in;
        }
      }
      if (nextTransferAmount > bytesToTransfer)
        nextTransferAmount = bytesToTransfer;
      // assert斷言的作用是,若nextTransferAmount <= 0,則終止程序。
      assert(nextTransferAmount > 0);
      // 將數(shù)據(jù)寫入到緩沖中
      System.arraycopy(b, off, buffer, in, nextTransferAmount);
      bytesToTransfer -= nextTransferAmount;
      off += nextTransferAmount;
      in += nextTransferAmount;
      if (in >= buffer.length) {
        in = 0;
      }
    }
  }
 
  // 檢查管道狀態(tài)
  private void checkStateForReceive() throws IOException {
    if (!connected) {
      throw new IOException("Pipe not connected");
    } else if (closedByWriter || closedByReader) {
      throw new IOException("Pipe closed");
    } else if (readSide != null && !readSide.isAlive()) {
      throw new IOException("Read end dead");
    }
  }
 
  // 等待。
  // 若“寫入管道”的數(shù)據(jù)正好全部被讀取完(例如,管道緩沖滿),則執(zhí)行awaitSpace()操作;
  // 它的目的是讓“讀取管道的線程”管道產(chǎn)生讀取數(shù)據(jù)請求,從而才能繼續(xù)的向“管道”中寫入數(shù)據(jù)。
  private void awaitSpace() throws IOException {
    
    // 如果“管道中被讀取的數(shù)據(jù),等于寫入管道的數(shù)據(jù)”時,
    // 則每隔1000ms檢查“管道狀態(tài)”,并喚醒管道操作:若有“讀取管道數(shù)據(jù)線程被阻塞”,則喚醒該線程。
    while (in == out) {
      checkStateForReceive();
 
      /* full: kick any waiting readers */
      notifyAll();
      try {
        wait(1000);
      } catch (InterruptedException ex) {
        throw new java.io.InterruptedIOException();
      }
    }
  }
 
  // 當(dāng)PipedOutputStream被關(guān)閉時,被調(diào)用
  synchronized void receivedLast() {
    closedByWriter = true;
    notifyAll();
  }
 
  // 從管道(的緩沖)中讀取一個字節(jié),并將其轉(zhuǎn)換成int類型
  public synchronized int read() throws IOException {
    if (!connected) {
      throw new IOException("Pipe not connected");
    } else if (closedByReader) {
      throw new IOException("Pipe closed");
    } else if (writeSide != null && !writeSide.isAlive()
          && !closedByWriter && (in < 0)) {
      throw new IOException("Write end dead");
    }
 
    readSide = Thread.currentThread();
    int trials = 2;
    while (in < 0) {
      if (closedByWriter) {
        /* closed by writer, return EOF */
        return -1;
      }
      if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
        throw new IOException("Pipe broken");
      }
      /* might be a writer waiting */
      notifyAll();
      try {
        wait(1000);
      } catch (InterruptedException ex) {
        throw new java.io.InterruptedIOException();
      }
    }
    int ret = buffer[out++] & 0xFF;
    if (out >= buffer.length) {
      out = 0;
    }
    if (in == out) {
      /* now empty */
      in = -1;
    }
 
    return ret;
  }
 
  // 從管道(的緩沖)中讀取數(shù)據(jù),并將其存入到數(shù)組b中
  public synchronized int read(byte b[], int off, int len) throws IOException {
    if (b == null) {
      throw new NullPointerException();
    } else if (off < 0 || len < 0 || len > b.length - off) {
      throw new IndexOutOfBoundsException();
    } else if (len == 0) {
      return 0;
    }
 
    /* possibly wait on the first character */
    int c = read();
    if (c < 0) {
      return -1;
    }
    b[off] = (byte) c;
    int rlen = 1;
    while ((in >= 0) && (len > 1)) {
 
      int available;
 
      if (in > out) {
        available = Math.min((buffer.length - out), (in - out));
      } else {
        available = buffer.length - out;
      }
 
      // A byte is read beforehand outside the loop
      if (available > (len - 1)) {
        available = len - 1;
      }
      System.arraycopy(buffer, out, b, off + rlen, available);
      out += available;
      rlen += available;
      len -= available;
 
      if (out >= buffer.length) {
        out = 0;
      }
      if (in == out) {
        /* now empty */
        in = -1;
      }
    }
    return rlen;
  }
 
  // 返回不受阻塞地從此輸入流中讀取的字節(jié)數(shù)。
  public synchronized int available() throws IOException {
    if(in < 0)
      return 0;
    else if(in == out)
      return buffer.length;
    else if (in > out)
      return in - out;
    else
      return in + buffer.length - out;
  }
 
  // 關(guān)閉管道輸入流
  public void close() throws IOException {
    closedByReader = true;
    synchronized (this) {
      in = -1;
    }
  }
}

管道通信示例

下面,我們看看多線程中通過管道通信的例子。例子中包括3個類:Receiver.java, PipedStreamTest.java 和 Sender.java。

Receiver.java的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import java.io.IOException; 
  
import java.io.PipedInputStream; 
  
@SuppressWarnings("all"
/**
 * 接收者線程
 */
public class Receiver extends Thread { 
    
  // 管道輸入流對象。
  // 它和“管道輸出流(PipedOutputStream)”對象綁定,
  // 從而可以接收“管道輸出流”的數(shù)據(jù),再讓用戶讀取。
  private PipedInputStream in = new PipedInputStream(); 
  
  // 獲得“管道輸入流”對象
  public PipedInputStream getInputStream(){ 
    return in; 
  
    
  @Override
  public void run(){ 
    readMessageOnce() ;
    //readMessageContinued() ;
  }
 
  // 從“管道輸入流”中讀取1次數(shù)據(jù)
  public void readMessageOnce(){
    // 雖然buf的大小是2048個字節(jié),但最多只會從“管道輸入流”中讀取1024個字節(jié)。
    // 因為,“管道輸入流”的緩沖區(qū)大小默認(rèn)只有1024個字節(jié)。
    byte[] buf = new byte[2048];
    try {
      int len = in.read(buf);
      System.out.println(new String(buf,0,len));
      in.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  // 從“管道輸入流”讀取>1024個字節(jié)時,就停止讀取
  public void readMessageContinued() {
    int total=0;
    while(true) {
      byte[] buf = new byte[1024];
      try {
        int len = in.read(buf);
        total += len;
        System.out.println(new String(buf,0,len));
        // 若讀取的字節(jié)總數(shù)>1024,則退出循環(huán)。
        if (total > 1024)
          break;
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
 
    try {
      in.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

Sender.java的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import java.io.IOException; 
  
import java.io.PipedOutputStream; 
@SuppressWarnings("all")
/**
 * 發(fā)送者線程
 */
public class Sender extends Thread { 
    
  // 管道輸出流對象。
  // 它和“管道輸入流(PipedInputStream)”對象綁定,
  // 從而可以將數(shù)據(jù)發(fā)送給“管道輸入流”的數(shù)據(jù),然后用戶可以從“管道輸入流”讀取數(shù)據(jù)。
  private PipedOutputStream out = new PipedOutputStream();
 
  // 獲得“管道輸出流”對象
  public PipedOutputStream getOutputStream(){
    return out;
  
 
  @Override
  public void run(){ 
    writeShortMessage();
    //writeLongMessage();
  
 
  // 向“管道輸出流”中寫入一則較簡短的消息:"this is a short message"
  private void writeShortMessage() {
    String strInfo = "this is a short message" ;
    try {
      out.write(strInfo.getBytes());
      out.close(); 
    } catch (IOException e) { 
      e.printStackTrace(); 
    
  }
  // 向“管道輸出流”中寫入一則較長的消息
  private void writeLongMessage() {
    StringBuilder sb = new StringBuilder();
    // 通過for循環(huán)寫入1020個字節(jié)
    for (int i=0; i<102; i++)
      sb.append("0123456789");
    // 再寫入26個字節(jié)。
    sb.append("abcdefghijklmnopqrstuvwxyz");
    // str的總長度是1020+26=1046個字節(jié)
    String str = sb.toString();
    try {
      // 將1046個字節(jié)寫入到“管道輸出流”中
      out.write(str.getBytes());
      out.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

PipedStreamTest.java的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.IOException;
 
@SuppressWarnings("all"
/**
 * 管道輸入流和管道輸出流的交互程序
 */
public class PipedStreamTest { 
  
  public static void main(String[] args) { 
    Sender t1 = new Sender(); 
      
    Receiver t2 = new Receiver(); 
      
    PipedOutputStream out = t1.getOutputStream(); 
 
    PipedInputStream in = t2.getInputStream(); 
 
    try
      //管道連接。下面2句話的本質(zhì)是一樣。
      //out.connect(in); 
      in.connect(out); 
        
      /**
       * Thread類的START方法:
       * 使該線程開始執(zhí)行;Java 虛擬機(jī)調(diào)用該線程的 run 方法。 
       * 結(jié)果是兩個線程并發(fā)地運行;當(dāng)前線程(從調(diào)用返回給 start 方法)和另一個線程(執(zhí)行其 run 方法)。 
       * 多次啟動一個線程是非法的。特別是當(dāng)線程已經(jīng)結(jié)束執(zhí)行后,不能再重新啟動。 
       */
      t1.start();
      t2.start();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

運行結(jié)果:

this is a short message

說明:
(01) 

in.connect(out); 

將“管道輸入流”和“管道輸出流”關(guān)聯(lián)起來。查看PipedOutputStream.java和PipedInputStream.java中connect()的源碼;我們知道 out.connect(in); 等價于 in.connect(out);

(02)
t1.start(); // 啟動“Sender”線程
t2.start(); // 啟動“Receiver”線程

先查看Sender.java的源碼,線程啟動后執(zhí)行run()函數(shù);在Sender.java的run()中,調(diào)用writeShortMessage();
writeShortMessage();的作用就是向“管道輸出流”中寫入數(shù)據(jù)"this is a short message" ;這條數(shù)據(jù)會被“管道輸入流”接收到。下面看看這是如何實現(xiàn)的。
先看write(byte b[])的源碼,在OutputStream.java中定義。PipedOutputStream.java繼承于OutputStream.java;OutputStream.java中write(byte b[])的源碼如下:

?
1
2
3
public void write(byte b[]) throws IOException {
  write(b, 0, b.length);
}

實際上write(byte b[])是調(diào)用的PipedOutputStream.java中的write(byte b[], int off, int len)函數(shù)。查看write(byte b[], int off, int len)的源碼,我們發(fā)現(xiàn):它會調(diào)用 sink.receive(b, off, len); 進(jìn)一步查看receive(byte b[], int off, int len)的定義,我們知道sink.receive(b, off, len)的作用就是:將“管道輸出流”中的數(shù)據(jù)保存到“管道輸入流”的緩沖中。而“管道輸入流”的緩沖區(qū)buffer的默認(rèn)大小是1024個字節(jié)。

至此,我們知道:t1.start()啟動Sender線程,而Sender線程會將數(shù)據(jù)"this is a short message"寫入到“管道輸出流”;而“管道輸出流”又會將該數(shù)據(jù)傳輸給“管道輸入流”,即而保存在“管道輸入流”的緩沖中。

接下來,我們看看“用戶如何從‘管道輸入流'的緩沖中讀取數(shù)據(jù)”。這實際上就是Receiver線程的動作。
t2.start() 會啟動Receiver線程,從而執(zhí)行Receiver.java的run()函數(shù)。查看Receiver.java的源碼,我們知道run()調(diào)用了readMessageOnce()。

而readMessageOnce()就是調(diào)用in.read(buf)從“管道輸入流in”中讀取數(shù)據(jù),并保存到buf中。
通過上面的分析,我們已經(jīng)知道“管道輸入流in”的緩沖中的數(shù)據(jù)是"this is a short message";因此,buf的數(shù)據(jù)就是"this is a short message"。

為了加深對管道的理解。我們接著進(jìn)行下面兩個小試驗。

試驗一:修改Sender.java

?
1
2
3
4
public void run(){ 
  writeShortMessage();
  //writeLongMessage();
}

修改為

?
1
2
3
4
public void run(){ 
  //writeShortMessage();
  writeLongMessage();
}

運行程序。運行結(jié)果為:

01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789abcd 

這些數(shù)據(jù)是通過writeLongMessage()寫入到“管道輸出流”,然后傳送給“管道輸入流”,進(jìn)而存儲在“管道輸入流”的緩沖中;再被用戶從緩沖讀取出來的數(shù)據(jù)。

然后,觀察writeLongMessage()的源碼。我們可以發(fā)現(xiàn),str的長度是1046個字節(jié),然后運行結(jié)果只有1024個字節(jié)!為什么會這樣呢?

道理很簡單:管道輸入流的緩沖區(qū)默認(rèn)大小是1024個字節(jié)。所以,最多只能寫入1024個字節(jié)。

觀察PipedInputStream.java的源碼,我們能了解的更透徹。

?
1
2
3
4
private static final int DEFAULT_PIPE_SIZE = 1024;
public PipedInputStream() {
  initPipe(DEFAULT_PIPE_SIZE);
}

默認(rèn)構(gòu)造函數(shù)調(diào)用initPipe(DEFAULT_PIPE_SIZE),它的源碼如下:

?
1
2
3
4
5
6
private void initPipe(int pipeSize) {
   if (pipeSize <= 0) {
    throw new IllegalArgumentException("Pipe Size <= 0");
   }
   buffer = new byte[pipeSize];
}

從中,我們可以知道緩沖區(qū)buffer的默認(rèn)大小就是1024個字節(jié)。

試驗二: 在“試驗一”的基礎(chǔ)上繼續(xù)修改Receiver.java

?
1
2
3
4
public void run(){ 
  readMessageOnce() ;
  //readMessageContinued() ;
}

修改為

?
1
2
3
4
public void run(){ 
  //readMessageOnce() ;
  readMessageContinued() ;
}

運行程序。運行結(jié)果為:
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789abcd
efghijklmnopqrstuvwxyz

這個結(jié)果才是writeLongMessage()寫入到“輸入緩沖區(qū)”的完整數(shù)據(jù)。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 无码11久岁箩筣 | 超级乱淫1| 草草线在成年免费视频网站 | 牛牛色婷婷在线视频播放 | 2018久久精品热在线观看 | 久久视热频国产这里只有精品23 | 肥胖女人一级毛片 | 精品国产一二三区在线影院 | 福利一区三区 | 6080欧美一区二区三区四区 | 三上悠亚精品专区久久 | 久久久久免费视频 | 扒开女人屁股眼看个够 | 美女任你摸| 欧美一级欧美一级高清 | 男人猛进猛出女人下面视频 | 亚欧日韩 | 狠狠色狠狠色综合日日小蛇 | 国产欧美日韩在线不卡第一页 | 日本高清不卡一区久久精品 | 99久久精品免费看国产四区 | 9191视频 | 免费看黄色片的网站 | 91国内在线国内在线播放 | 丰满岳乱妇在线观看视频国产 | 92国产福利视频一区二区 | 91香蕉国产 | 精品午夜寂寞影院在线观看 | 亚洲不卡视频 | 亚洲网站在线播放 | 男插女的下面免费视频夜色 | 视频免费视频观看网站 | 国产精品原创巨作无遮挡 | ipx-177绝对领域在线观看 | b站免费 | 狠狠色成人综合网图片区 | 日本高清有码视频 | 欧美a欧美1级 | 精品国产91久久久久 | 国产偷啪 | 日韩无砖专区2020在线 |