For example, the thread communication control of piped pipeline input and output flow in Java _java

Source: Internet
Author: User
Tags thread class

PipedOutputStream and PipedInputStream

In Java, PipedOutputStream and pipedinputstream are pipe output streams and pipe input streams respectively.
Their role is to allow multithreading to communicate between threads through the pipeline. PipedOutputStream and PipedInputStream must be used to support the use of piping communications.
When using duct communication, the approximate process is that we write the data to the PipedOutputStream in thread A, which is automatically sent to the pipedinputstream corresponding to the PipedOutputStream. It is then stored in a PipedInputStream buffer, at which point thread B reads the data in the PipedInputStream. Can be implemented, thread A and thread B communication.
Below, let's look at the example of pipeline communication across multiple threads. Examples include 3 classes: Receiver.java, Pipedstreamtest.java and Sender.java.
The code for Receiver.java is as follows:

Import java.io.IOException; 

Import Java.io.PipedInputStream;
 The @SuppressWarnings ("all")/** * Recipient thread/public class Receiver extends thread {//Pipeline input object.
 It is bound to the pipe output stream (PipedOutputStream) object,//So you can receive the "Pipe output stream" data and then let the user read it. 

 Private PipedInputStream in = new PipedInputStream (); 
 Get the pipeline Inflow object public PipedInputStream getInputStream () {return in;
  @Override public void Run () {readmessageonce ();
 Readmessagecontinued ();
  ///read 1 data from the pipeline inlet readmessageonce () {//Although the size of the BUF is 2048 bytes, it will read up to 1024 bytes from the pipeline input.
  Because the buffer size for pipeline inflow is only 1024 bytes by default.
  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 ();
  To stop reading the public void readmessagecontinued () {int total=0, when reading >1024 bytes from "Pipeline input";
   while (true) {byte[] buf = new byte[1024];
    try {int len = In.read (BUF);
    Total = Len; System.out.println (New String (buf, 0,len));
    If the total number of bytes Read is >1024, the loop is exited.
   if (Total > 1024) break;
   catch (IOException e) {e.printstacktrace ();
  } try {in.close ();
  catch (IOException e) {e.printstacktrace ();

 }
 }
}

The

Sender.java code is as follows:

Import java.io.IOException; 
Import Java.io.PipedOutputStream;
 @SuppressWarnings ("All")/** * Sender thread/public class Sender extends thread {//Pipe output stream object.
 It is bound to the pipe input stream (PipedInputStream) object,//so that data can be sent to pipeline inflow, and users can then read data from pipeline inflow.

 Private PipedOutputStream out = new PipedOutputStream ();
 Get the pipe output stream object public PipedOutputStream Getoutputstream () {return out;
  @Override public void Run () {writeshortmessage ();
 Writelongmessage (); Write a shorter message to the pipeline output stream: "This is a short news" private void Writeshortmessage () {String Strinfo = "This is a s
  Hort message ";
   try {out.write (strinfo.getbytes ()); 
  Out.close (); 
  catch (IOException e) {e.printstacktrace ();
  Write a long message to the pipeline output stream private void Writelongmessage () {StringBuilder sb = new StringBuilder ();
  Writes 1020 bytes for (int i=0; i<102; i++) sb.append ("0123456789") through a For loop;
  Write 26 bytes again.
  Sb.append ("abcdefghijklmnopqrstuvwxyz"); The total length of STR is 1020+26=1046 byte String sTR = sb.tostring ();
   try {//1046 bytes are written to the pipeline output stream Out.write (Str.getbytes ());
  Out.close ();
  catch (IOException e) {e.printstacktrace ();

 }
 }
}

The code for Pipedstreamtest.java is as follows:

Import Java.io.PipedInputStream;
Import Java.io.PipedOutputStream;
Import java.io.IOException;

@SuppressWarnings ("All") 
/** 
 * Interface between pipeline inflow and pipeline output flow/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 { 
   //pipe connection. The following 2 words are essentially the same.
   //out.connect (in); 
   In.connect (out); 

   The 
    start method for the/** * Thread class: 
    * Causes the thread to start executing; the Java virtual machine invokes the thread's Run method. 
    * The result is two threads running concurrently, when the line (returned from the call to the Start method) and another thread (executing its Run method). 
    * It is illegal to start a thread multiple times. Especially when the thread has finished executing, it cannot be restarted. 
    * *
   t1.start ();
   T2.start ();
  } catch (IOException e) {
   e.printstacktrace ();}}}


Run Result:

This is a short message

Description
(1) In.connect (out); associate "Pipeline inflow" with "pipeline output stream". View the source of Connect () in Pipedoutputstream.java and Pipedinputstream.java; we know Out.connect (in); Equivalent to In.connect (out);
(2)

T1.start (); Start the "Sender" Thread 
t2.start ();//Start the "Receiver" thread

First look at the source of the Sender.java, the thread to start the run () function, in Sender.java run (), invoke Writeshortmessage ();
The role of Writeshortmessage () is to write data to the pipeline output stream, "This is a short message", which will be received by the "Pipeline inflow". Let's see how this is achieved.
First look at the source code of write (byte b[]), defined in Outputstream.java. Pipedoutputstream.java inherits from the source code in Outputstream.java;outputstream.java write (Byte b[]) as follows:

public void Write (byte b[]) throws IOException {
 write (b, 0, b.length);

Actually write (byte b[]) is the write (byte b[], int off, int len) function in the called Pipedoutputstream.java. Looking at the source code for write (byte b[], int off, int len), we found that: it will call Sink.receive (b, off, Len); For a further look at the definition of receive (byte b[], int off, int len), we know that the role of sink.receive (b, off, Len) is to save the data in the pipeline output stream to a buffer of pipeline inflow. The default size of buffer buffers for "pipeline inflow" is 1024 bytes.
At this point, we know that the T1.start () starts the sender thread, and the sender thread writes the data "This is a short message" to the pipeline output stream, and the pipeline output stream transfers the transfer to the "pipeline inflow", which is saved in the pipeline inflow "In the buffer.
Next, let's take a look at how users can read data from the ' pipeline inflow ' buffer. This is actually the action of the receiver thread.
T2.start () starts the receiver thread and executes the Receiver.java run () function. Looking at the Receiver.java source, we know that run () called Readmessageonce ().
The Readmessageonce () is called In.read (BUF) to read the data from "pipe input stream in" and save it to the BUF.
Through the above analysis, we already know that the data in the buffer of "pipe input flow in" are "this was a short message"; Therefore, the BUF data is the "this are a short message".
In order to deepen the understanding of the pipeline. We proceeded to the following two small trials.
Test One: Modify Sender.java
Will

public void Run () { 
 writeshortmessage ();
 Writelongmessage ();
} 

Amended to

public void Run () { 
 //writeshortmessage ();
 Writelongmessage ();
}

Run the program. The results of the operation are:

01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789abcd
 

The data is written to the pipe output stream by Writelongmessage () and then transferred to the pipeline inlet, which is then stored in a "pipeline inflow" buffer, and is read by the user from the buffer.
Then, observe the source code of Writelongmessage (). We can see that the length of STR is 1046 bytes and then the result is only 1024 bytes! Why is that?
The reason is simple: the default size of the buffer for pipeline inflow is 1024 bytes. So, you can write up to 1024 bytes.
Observe the source code of Pipedinputstream.java, we can understand more thoroughly.

private static final int default_pipe_size = 1024;
Public PipedInputStream () {
 initpipe (default_pipe_size);
}

The default constructor calls Initpipe (Default_pipe_size), and its source code is as follows:

private void Initpipe (int pipesize) {
  if (pipesize <= 0) {
  throw new IllegalArgumentException ("Pipe Size <= 0 ");
  }
  Buffer = new Byte[pipesize];
}

From this, we can know that the default size of buffer buffers is 1024 bytes.
Test two: Continue to modify receiver.java on the basis of "test one"
Will

public void Run () { 
 readmessageonce ();
 Readmessagecontinued ();
}

Amended to

public void Run () { 
 //readmessageonce ();
 Readmessagecontinued ();
}

Run the program. The results of the operation are:

01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789ABCD efghijklmnopqrstuvwxyz
 

This result is the full data written to the "input buffer" by Writelongmessage ().

PipedWriter and Pipedreader
PipedWriter is a character pipeline output stream that inherits from writer.
Pipedreader is a character pipeline input stream that inherits from writer.
The role of PipedWriter and Pipedreader is to communicate between threads through a pipeline. PipedWriter and Pipedreader must be used to support the use of piping communications.
Below, let's look at the examples of PipedWriter and Pipedreader communications across multiple threads. Examples include 3 classes: Receiver.java, Sender.java and Pipetest.java
The code for Receiver.java is as follows:

Import java.io.IOException; 

Import Java.io.PipedReader;
 The @SuppressWarnings ("all")/** * Recipient thread/public class Receiver extends thread {//Pipeline input object.
 It is bound to the pipe output stream (PipedWriter) object,//So you can receive the "Pipe output stream" data and then let the user read it. 

 Private Pipedreader in = new Pipedreader (); 
 Gets the "pipeline stream stream object" public Pipedreader Getreader () {return in;
  @Override public void Run () {readmessageonce ();
 Readmessagecontinued ();
  ///read 1 data from "pipeline input" {readmessageonce () {//Although the size of the BUF is 2048 characters, it will read up to 1024 characters from the pipeline input.
  Because the buffer size for pipeline inflow is only 1024 characters by default. 
  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 ();
  To stop reading the public void readmessagecontinued () {int total=0, when reading >1024 characters from "Pipeline input";
   while (true) {char[] buf = new char[1024];
    try {int len = In.read (BUF);
    Total = Len;
    System.out.println (New String (Buf,0,len)); If you read the>1024 the total number of characters, exit the loop.
   if (Total > 1024) break;
   catch (IOException e) {e.printstacktrace (); 
  } try {in.close (); 
  catch (IOException e) {e.printstacktrace ();

 } 
 } 
}

The

Sender.java code is as follows:

Import java.io.IOException; 
Import Java.io.PipedWriter;
 @SuppressWarnings ("All")/** * Sender thread/public class Sender extends thread {//Pipe output stream object.
 It is bound to the pipe input stream (Pipedreader) object,//so that data can be sent to pipeline inflow, and users can then read data from pipeline inflow.

 Private PipedWriter out = new PipedWriter ();
 Get the pipe output stream object public PipedWriter getwriter () {return out;
  @Override public void Run () {writeshortmessage ();
 Writelongmessage (); Write a shorter message to the pipeline output stream: "This is a short news" private void Writeshortmessage () {String Strinfo = "This is a s
  Hort message ";
   try {out.write (Strinfo.tochararray ()); 
  Out.close (); 
  catch (IOException e) {e.printstacktrace ();
  Write a long message to the pipeline output stream private void Writelongmessage () {StringBuilder sb = new StringBuilder ();
  Writes 1020 characters for (int i=0; i<102; i++) sb.append ("0123456789") through a For loop;
  Write 26 characters again.
  Sb.append ("abcdefghijklmnopqrstuvwxyz");
  The total length of STR is 1020+26=1046 character String str = sb.tostring ();
   try {Writes 1046 characters to the pipe output stream out.write (str);
  Out.close ();
  catch (IOException e) {e.printstacktrace ();

 }
 }
}

The code for Pipetest.java is as follows:

Import Java.io.PipedReader;
Import Java.io.PipedWriter;
Import java.io.IOException;

@SuppressWarnings ("All") 
/** 
 * Interface for pipeline inflow and pipeline output flow/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 { 
   //pipe connection. The following 2 words are essentially the same.
   //out.connect (in); 
   In.connect (out); 

   The 
    start method for the/** * Thread class: 
    * Causes the thread to start executing; the Java virtual machine invokes the thread's Run method. 
    * The result is two threads running concurrently, when the line (returned from the call to the Start method) and another thread (executing its Run method). 
    * It is illegal to start a thread multiple times. Especially when the thread has finished executing, it cannot be restarted. 
    * *
   t1.start ();
   T2.start ();
  } catch (IOException e) {
   e.printstacktrace ();}}}


Run Result:
This is a short message
Results show:

(1)

 In.connect (out);

Its role is to associate "pipeline inflow" with "pipeline output stream". View the source of Connect () in Pipedwriter.java and Pipedreader.java; we know Out.connect (in); Equivalent to In.connect (out);
(2)

T1.start (); Start the "Sender" Thread
t2.start ();//Start the "Receiver" thread

First look at the source of the Sender.java, the thread to start the run () function, in Sender.java run (), invoke Writeshortmessage ();
The role of Writeshortmessage () is to write data to the pipeline output stream, "This is a short message", which will be received by the "Pipeline inflow". Let's see how this is achieved.
First read the Write (char char source code.) Pipedwriter.java inherits from the source code in Writer.java;writer.java write (char c[]) as follows:

public void Write (char cbuf[]) throws IOException {
 write (cbuf, 0, cbuf.length);


Actually write (char c[]) is the write (char c[], int off, int len) function in the called Pipedwriter.java. Looking at the source code for write (char c[], int off, int len), we found that: it will call Sink.receive (Cbuf, off, Len); For further review of the definition of receive (char c[], int off, int len), we know that the role of sink.receive (Cbuf, off, Len) is to save the data in the pipeline output stream to a buffer of pipeline inflow. The default size of buffer buffers for "pipeline inflow" is 1024 characters.
At this point, we know that the T1.start () starts the sender thread, and the sender thread writes the data "This is a short message" to the pipeline output stream, and the pipeline output stream transfers the transfer to the "pipeline inflow", which is saved in the pipeline inflow "In the buffer.
Next, let's take a look at how users can read data from the ' pipeline inflow ' buffer. This is actually the action of the receiver thread.
T2.start () starts the receiver thread and executes the Receiver.java run () function. Looking at the Receiver.java source, we know that run () called Readmessageonce ().
The Readmessageonce () is called In.read (BUF) to read the data from "pipe input stream in" and save it to the BUF.
Through the above analysis, we already know that the data in the buffer of "pipe input flow in" are "this was a short message"; Therefore, the BUF data is the "this are a short message".
In order to deepen the understanding of the pipeline. We proceeded to the following two small trials.
Test One: Modify Sender.java
Will

public void Run () { 
 writeshortmessage ();
 Writelongmessage ();
}

Amended to

public void Run () { 
 //writeshortmessage ();
 Writelongmessage ();
}

Run the program. The results of the operation are as follows:

From that, we see that the program runs wrong! Throw an exception java.io.IOException:Pipe closed
Why is that?
Let me analyze the procedure flow.
(1) in pipetest, the input and output pipes are connected by In.connect (out), then two threads are started. T1.start () started thread Sender,t2.start () started thread receiver.
(2) After the sender thread starts, writes the data to the output pipeline through Writelongmessage (), Out.write (Str.tochararray ()) writes 1046 characters altogether. According to PipedWriter's source code, PipedWriter's write () function invokes the Pipedreader receive () function. While observing the Pipedreader receive () function, we know that Pipedreader will receive the data stored in the buffer. Carefully observe the receive () function, with the following code:

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 ();
 }
}

The initial values of in and out are In=-1, out=0, and the above while (in==out) are combined. As we know, it means that each character is written to the pipe, and the in==out is reached. Then, call Notifyall () and wake up the thread that reads the pipe.
That is, each character written to the pipeline is blocked waiting for the other thread to read.
However, the default size of the Pipedreader buffer is 1024! However, the data to be written at this time is 1046! As a result, you can write up to 1024 characters at a maximum.
(receiver) The readmessageonce () read the pipeline input stream is invoked after the thread is started. Reading 1024 characters will call Close () closed, pipe.
From the analysis of (02) and (03), Sender writes 1046 characters to the pipe. Where the first 1024 characters (the buffer capacity is 1024) can be written correctly, and one is read per write. When 1025 characters are written, the write () in the Pipedwriter.java is still called sequentially, and the receive () in Pipedreader.java is invoked in write (). ; in Pipedreader.java, it is eventually called to the receive (int c) function. At this point, the pipeline inflow has been closed, that is, Closedbyreader is true, so the throw new IOException ("Pipe closed") is thrown.
We continue to modify the "test one" to solve the problem.
Test two: On the basis of "test one" to continue to modify Receiver.java will

public void Run () { 
 readmessageonce ();
 Readmessagecontinued ();
}

Amended to

public void Run () { 
 //readmessageonce ();
 Readmessagecontinued ();
}

At this point, the program works correctly. The result of the run is:

01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789ABCD efghijklmnopqrstuvwxyz
 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.