国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

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

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - 舉例講解Java中Piped管道輸入輸出流的線程通信控制

舉例講解Java中Piped管道輸入輸出流的線程通信控制

2020-05-22 10:50skywangkw JAVA教程

Java中的PipedWriter、PipedReader類管道的讀寫依賴于PipedOutputStream、PipedInputStream兩個(gè)管道輸入輸出類,這里我們將來舉例講解Java中Piped管道輸入輸出流的線程通信控制:

PipedOutputStream和PipedInputStream

在java中,PipedOutputStream和PipedInputStream分別是管道輸出流和管道輸入流。
它們的作用是讓多線程可以通過管道進(jìn)行線程間的通訊。在使用管道通信時(shí),必須將PipedOutputStream和PipedInputStream配套使用。
使用管道通信時(shí),大致的流程是:我們在線程A中向PipedOutputStream中寫入數(shù)據(jù),這些數(shù)據(jù)會自動的發(fā)送到與PipedOutputStream對應(yīng)的PipedInputStream中,進(jìn)而存儲在PipedInputStream的緩沖中;此時(shí),線程B通過讀取PipedInputStream中的數(shù)據(jù)。就可以實(shí)現(xiàn),線程A和線程B的通信。
下面,我們看看多線程中通過管道通信的例子。例子中包括3個(gè)類: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個(gè)字節(jié),但最多只會從“管道輸入流”中讀取1024個(gè)字節(jié)。
  // 因?yàn)椋?ldquo;管道輸入流”的緩沖區(qū)大小默認(rèn)只有1024個(gè)字節(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個(gè)字節(jié)時(shí),就停止讀取
 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個(gè)字節(jié)
  for (int i=0; i<102; i++)
   sb.append("0123456789");
  // 再寫入26個(gè)字節(jié)。
  sb.append("abcdefghijklmnopqrstuvwxyz");
  // str的總長度是1020+26=1046個(gè)字節(jié)
  String str = sb.toString();
  try {
   // 將1046個(gè)字節(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é)果是兩個(gè)線程并發(fā)地運(yùn)行;當(dāng)前線程(從調(diào)用返回給 start 方法)和另一個(gè)線程(執(zhí)行其 run 方法)。
    * 多次啟動一個(gè)線程是非法的。特別是當(dāng)線程已經(jīng)結(jié)束執(zhí)行后,不能再重新啟動。
    */
   t1.start();
   t2.start();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

運(yùn)行結(jié)果:

?
1
this is a short message

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

?
1
2
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ù)會被“管道輸入流”接收到。下面看看這是如何實(shí)現(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);
}

實(shí)際上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個(gè)字節(jié)。
至此,我們知道:t1.start()啟動Sender線程,而Sender線程會將數(shù)據(jù)"this is a short message"寫入到“管道輸出流”;而“管道輸出流”又會將該數(shù)據(jù)傳輸給“管道輸入流”,即而保存在“管道輸入流”的緩沖中。
接下來,我們看看“用戶如何從‘管道輸入流'的緩沖中讀取數(shù)據(jù)”。這實(shí)際上就是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)行下面兩個(gè)小試驗(yàn)。
試驗(yàn)一:修改Sender.java

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

修改為

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

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

?
1
2
3
4
5
6
7
8
9
10
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789abcd

這些數(shù)據(jù)是通過writeLongMessage()寫入到“管道輸出流”,然后傳送給“管道輸入流”,進(jìn)而存儲在“管道輸入流”的緩沖中;再被用戶從緩沖讀取出來的數(shù)據(jù)。
然后,觀察writeLongMessage()的源碼。我們可以發(fā)現(xiàn),str的長度是1046個(gè)字節(jié),然后運(yùn)行結(jié)果只有1024個(gè)字節(jié)!為什么會這樣呢?
道理很簡單:管道輸入流的緩沖區(qū)默認(rèn)大小是1024個(gè)字節(jié)。所以,最多只能寫入1024個(gè)字節(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個(gè)字節(jié)。
試驗(yàn)二: 在“試驗(yàn)一”的基礎(chǔ)上繼續(xù)修改Receiver.java

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

修改為

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

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

?
1
2
3
4
5
6
7
8
9
10
11
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789abcd
efghijklmnopqrstuvwxyz

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

PipedWriter和PipedReader
PipedWriter 是字符管道輸出流,它繼承于Writer。
PipedReader 是字符管道輸入流,它繼承于Writer。
PipedWriter和PipedReader的作用是可以通過管道進(jìn)行線程間的通訊。在使用管道通信時(shí),必須將PipedWriter和PipedReader配套使用。
下面,我們看看多線程中通過PipedWriter和PipedReader通信的例子。例子中包括3個(gè)類:Receiver.java, Sender.java 和 PipeTest.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
64
import java.io.IOException;
 
import java.io.PipedReader;
 
@SuppressWarnings("all")
/**
 * 接收者線程
 */
public class Receiver extends Thread {
 
 // 管道輸入流對象。
 // 它和“管道輸出流(PipedWriter)”對象綁定,
 // 從而可以接收“管道輸出流”的數(shù)據(jù),再讓用戶讀取。
 private PipedReader in = new PipedReader();
 
 // 獲得“管道輸入流對象”
 public PipedReader getReader(){
  return in;
 }
 
 @Override
 public void run(){
  readMessageOnce() ;
  //readMessageContinued() ;
 }
 
 // 從“管道輸入流”中讀取1次數(shù)據(jù)
 public void readMessageOnce(){
  // 雖然buf的大小是2048個(gè)字符,但最多只會從“管道輸入流”中讀取1024個(gè)字符。
  // 因?yàn)椋?ldquo;管道輸入流”的緩沖區(qū)大小默認(rèn)只有1024個(gè)字符。
  char[] buf = new char[2048];
  try {
   int len = in.read(buf);
   System.out.println(new String(buf,0,len));
   in.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 
 // 從“管道輸入流”讀取>1024個(gè)字符時(shí),就停止讀取
 public void readMessageContinued(){
  int total=0;
  while(true) {
   char[] buf = new char[1024];
   try {
    int len = in.read(buf);
    total += len;
    System.out.println(new String(buf,0,len));
    // 若讀取的字符總數(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.PipedWriter;
@SuppressWarnings("all")
/**
 * 發(fā)送者線程
 */
public class Sender extends Thread {
 
 // 管道輸出流對象。
 // 它和“管道輸入流(PipedReader)”對象綁定,
 // 從而可以將數(shù)據(jù)發(fā)送給“管道輸入流”的數(shù)據(jù),然后用戶可以從“管道輸入流”讀取數(shù)據(jù)。
 private PipedWriter out = new PipedWriter();
 
 // 獲得“管道輸出流”對象
 public PipedWriter getWriter(){
  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.toCharArray());
   out.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 // 向“管道輸出流”中寫入一則較長的消息
 private void writeLongMessage() {
  StringBuilder sb = new StringBuilder();
  // 通過for循環(huán)寫入1020個(gè)字符
  for (int i=0; i<102; i++)
   sb.append("0123456789");
  // 再寫入26個(gè)字符。
  sb.append("abcdefghijklmnopqrstuvwxyz");
  // str的總長度是1020+26=1046個(gè)字符
  String str = sb.toString();
  try {
   // 將1046個(gè)字符寫入到“管道輸出流”中
   out.write(str);
   out.close();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

PipeTest.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.PipedReader;
import java.io.PipedWriter;
import java.io.IOException;
 
@SuppressWarnings("all")
/**
 * 管道輸入流和管道輸出流的交互程序
 */
public class PipeTest {
 
 public static void main(String[] args) {
  Sender t1 = new Sender();
 
  Receiver t2 = new Receiver();
 
  PipedWriter out = t1.getWriter();
 
  PipedReader in = t2.getReader();
 
  try {
   //管道連接。下面2句話的本質(zhì)是一樣。
   //out.connect(in);
   in.connect(out);
 
   /**
    * Thread類的START方法:
    * 使該線程開始執(zhí)行;Java 虛擬機(jī)調(diào)用該線程的 run 方法。
    * 結(jié)果是兩個(gè)線程并發(fā)地運(yùn)行;當(dāng)前線程(從調(diào)用返回給 start 方法)和另一個(gè)線程(執(zhí)行其 run 方法)。
    * 多次啟動一個(gè)線程是非法的。特別是當(dāng)線程已經(jīng)結(jié)束執(zhí)行后,不能再重新啟動。
    */
   t1.start();
   t2.start();
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}

運(yùn)行結(jié)果:
this is a short message
結(jié)果說明:

(1)

?
1
in.connect(out);

它的作用是將“管道輸入流”和“管道輸出流”關(guān)聯(lián)起來。查看PipedWriter.java和PipedReader.java中connect()的源碼;我們知道 out.connect(in); 等價(jià)于 in.connect(out);
(2)

?
1
2
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ù)會被“管道輸入流”接收到。下面看看這是如何實(shí)現(xiàn)的。
先看write(char char的源碼。PipedWriter.java繼承于Writer.java;Writer.java中write(char c[])的源碼如下:

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


實(shí)際上write(char c[])是調(diào)用的PipedWriter.java中的write(char c[], int off, int len)函數(shù)。查看write(char c[], int off, int len)的源碼,我們發(fā)現(xiàn):它會調(diào)用 sink.receive(cbuf, off, len); 進(jìn)一步查看receive(char c[], int off, int len)的定義,我們知道sink.receive(cbuf, off, len)的作用就是:將“管道輸出流”中的數(shù)據(jù)保存到“管道輸入流”的緩沖中。而“管道輸入流”的緩沖區(qū)buffer的默認(rèn)大小是1024個(gè)字符。
至此,我們知道:t1.start()啟動Sender線程,而Sender線程會將數(shù)據(jù)"this is a short message"寫入到“管道輸出流”;而“管道輸出流”又會將該數(shù)據(jù)傳輸給“管道輸入流”,即而保存在“管道輸入流”的緩沖中。
接下來,我們看看“用戶如何從‘管道輸入流'的緩沖中讀取數(shù)據(jù)”。這實(shí)際上就是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)行下面兩個(gè)小試驗(yàn)。
試驗(yàn)一:修改Sender.java

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

修改為

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

運(yùn)行程序。運(yùn)行結(jié)果如下:

舉例講解Java中Piped管道輸入輸出流的線程通信控制

從中,我們看出,程序運(yùn)行出錯(cuò)!拋出異常 java.io.IOException: Pipe closed
為什么會這樣呢?
我分析一下程序流程。
(1) 在PipeTest中,通過in.connect(out)將輸入和輸出管道連接起來;然后,啟動兩個(gè)線程。t1.start()啟動了線程Sender,t2.start()啟動了線程Receiver。
(2) Sender線程啟動后,通過writeLongMessage()寫入數(shù)據(jù)到“輸出管道”,out.write(str.toCharArray())共寫入了1046個(gè)字符。而根據(jù)PipedWriter的源碼,PipedWriter的write()函數(shù)會調(diào)用PipedReader的receive()函數(shù)。而觀察PipedReader的receive()函數(shù),我們知道,PipedReader會將接受的數(shù)據(jù)存儲緩沖區(qū)。仔細(xì)觀察receive()函數(shù),有如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
while (in == out) {
 if ((readSide != null) && !readSide.isAlive()) {
  throw new IOException("Pipe broken");
 }
 /* full: kick any waiting readers */
 notifyAll();
 try {
  wait(1000);
 } catch (InterruptedException ex) {
  throw new java.io.InterruptedIOException();
 }
}

而in和out的初始值分別是in=-1, out=0;結(jié)合上面的while(in==out)。我們知道,它的含義就是,每往管道中寫入一個(gè)字符,就達(dá)到了in==out這個(gè)條件。然后,就調(diào)用notifyAll(),喚醒“讀取管道的線程”。
也就是,每往管道中寫入一個(gè)字符,都會阻塞式的等待其它線程讀取。
然而,PipedReader的緩沖區(qū)的默認(rèn)大小是1024!但是,此時(shí)要寫入的數(shù)據(jù)卻有1046!所以,一次性最多只能寫入1024個(gè)字符。
(03) Receiver線程啟動后,會調(diào)用readMessageOnce()讀取管道輸入流。讀取1024個(gè)字符會,會調(diào)用close()關(guān)閉,管道。
由(02)和(03)的分析可知,Sender要往管道寫入1046個(gè)字符。其中,前1024個(gè)字符(緩沖區(qū)容量是1024)能正常寫入,并且每寫入一個(gè)就讀取一個(gè)。當(dāng)寫入1025個(gè)字符時(shí),依然是依次的調(diào)用PipedWriter.java中的write();然后,write()中調(diào)用PipedReader.java中的receive();在PipedReader.java中,最終又會調(diào)用到receive(int c)函數(shù)。 而此時(shí),管道輸入流已經(jīng)被關(guān)閉,也就是closedByReader為true,所以拋出throw new IOException("Pipe closed")。
我們對“試驗(yàn)一”繼續(xù)進(jìn)行修改,解決該問題。
試驗(yàn)二: 在“試驗(yàn)一”的基礎(chǔ)上繼續(xù)修改Receiver.java 將

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

修改為

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

此時(shí),程序能正常運(yùn)行。運(yùn)行結(jié)果為:

?
1
2
3
4
5
6
7
8
9
10
11
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
012345678901234567890123456789abcd
efghijklmnopqrstuvwxyz

 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品一二 | 日韩在线中文字幕 | 亚洲天堂久久 | 日日夜夜精品视频 | 久久久精品黄色 | 黄视频入口 | 色接久久 | 亚洲视频免费 | 日韩在线免费电影 | 午夜在线小视频 | 日韩免费在线 | 成人黄网视频在线观看 | 中文在线一区二区 | 国产精品久久久久久福利一牛影视 | 亚洲精品久久久久久久蜜桃 | 国产精品美女久久久 | bxbx成人精品一区二区三区 | 欧美精品一区二区三区蜜桃视频 | 亚洲视频在线观看网址 | 日韩a| 亚洲高清视频在线 | 欧美激情国产日韩精品一区18 | 精品一区在线 | 精品三级三级三级三级三级 | 国产精品网站在线观看 | 伊人99热 | 午夜免费av | 久久久美女 | 伦理午夜电影免费观看 | 成人av片在线观看 | 不用播放器的免费av | 成人黄色短视频在线观看 | 亚洲一区中文 | 综合久| 久久精品夜夜夜夜夜久久 | 中文字幕在线三区 | 91精品国产一区二区三区香蕉 | 在线手机电影 | 午夜精品久久久久久久99黑人 | 波多野结衣一区二区三区中文字幕 | 国产一卡二卡三卡 |