Java Fundamentals: non-blocking IO

Source: Internet
Author: User
Tags compact

Reprint Please specify the Source: Jiq ' s technical Blog

Introduction

NIO, or new IO, was introduced in JDK1.4 to improve IO speed. It is important to note that Javanio is not completely non-blocking IO (no-blocking io) because some of these channels (such as FileChannel) can only be run in blocking mode, while other channels may be selectable between blocking and non-blocking.

In spite of this, we are accustomed to think of Java NiO as non-blocking IO, and the previously described IO class library for stream (Byte/character) is non-blocking, and in detail, the difference is as follows:

io

nio

buffer-oriented (buffer oriented)

blocked (Blocking IO)

non-blocking (Non blocking IO)

none

selector (selectors)

But remember, the two are not superior or inferior, NIO is a java IO development, depending on the scene, both are useful.

Stream-oriented and buffer-oriented

The first major difference between Java NiO and Io is that IO is stream-oriented and NIO is buffer-oriented. The Javaio-oriented stream means that one or more bytes are read from the stream each time, until all bytes are read, and they are not being slowed anywhere. In addition, it cannot move data in the stream back and forth. If you need to move the data read from the stream before and after it, you need to cache it to a buffer first. Java NiO has a slightly different buffer-oriented approach. The data is read to a buffer that it processes later, and can be moved back and forth in the buffer if needed. This increases the flexibility of the process. However, you also need to check if the buffer contains all the data that you need to process. Also, make sure that when more data is read into the buffer, do not overwrite the data that has not been processed in the buffer.

Blocking and non-blocking IO

The various streams of Java Io are blocked. This means that when a thread calls read () or write (), the thread is blocked until some data is read, or the data is fully written. The thread can no longer do anything during this time. The non-blocking mode of Java NIO enables a thread to send requests to read data from a channel, but it can only get the data that is currently available and will not get anything if no data is available. Instead of keeping the thread blocked, the thread can continue to do other things until the data becomes readable. The same is true for non-blocking writes. A thread requests to write some data to a channel, but does not have to wait for it to be fully written, and the thread can do something else at the same time. Threads typically use non-blocking IO idle time to perform IO operations on other channels, so a single thread can now manage multiple input and output channels (channel).

Selector (selectors)

The Java NiO selector allows a single thread to monitor multiple input channels, you can register multiple channels using a selector, and then use a separate thread to "select" the channel: these channels already have inputs that can be processed, or select the channels that are ready to be written. This selection mechanism makes it easy for a single thread to manage multiple channels.

The three key concepts of Java NiO are channels, buffers, and selectors, respectively:

I. Channels (channel)

Java NiO channels are similar to streams, but are somewhat different:

N-channels are bidirectional, readable and writable, while stream reads and writes are unidirectional.

N-channels can be read and written asynchronously.

n both read and write, the channel can only interact with buffer.

The most important channel implementations in Javanio are:

U filechannel: Read and write data from a file.

U Datagramchannel: Reads and writes data from the network via UDP.

U Socketchannel: Reads and writes data from the network via TCP.

U serversocketchannel: You can listen for incoming TCP connections, like Web servers. A socketchannel is created for each new incoming connection.

Here is an example of writing data to a file via FileChannel:

public class Test {public   static void Main (string[] args) throws IOException  {       File File = new file ("Test.txt ");       FileOutputStream OS = new FileOutputStream (file);       FileChannel channel = Os.getchannel ();       Bytebuffer buffer = bytebuffer.allocate (1024x768);       String str = "Hello,jiyiqin";       Buffer.put (Str.getbytes ());       Buffer.flip ();       Channel.write (buffer);       Channel.close ();       Os.close ();   } }

Note: The above example has two key points: one is to get the channel through the FileOutputStream file output stream, the old IO class library (or the stream-oriented IO class library) fileinputstream/ FileOutputStream and Randomaccessfile three classes are modified to produce filechannel channels, but the character-oriented stream Reader/writer cannot produce a channel. In addition, the flip method that calls the buffer must be converted to read mode before the buffer data is written to the channel, allowing the channel to read the data from the buffer.


Second, buffer

Buffer in Java NiO is used to interact with the NIO channel, where the data is read from the channel into the buffer or written to the channel from the buffer. When data is written to buffer, buffer records how much data is written. Once you are reading the data, you need to switch the buffer from write mode to read mode via the Flip () method. In read mode, all data written to buffer can be read. Once all the data has been read, the buffer needs to be emptied so that it can be written again. There are two ways to clear a buffer: Call the Clear () or compact () method. The clear () method empties the entire buffer. The compact () method clears only the data that has been read. Any unread data is moved to the beginning of the buffer, and the newly written data is placed behind the buffer's unread data.

A buffer is essentially a piece of memory in which data can be written and then read from it. This memory is packaged into a NiO buffer object and provides a set of methods for easy access to the block memory.

Here is an example of reading data from a file channel FileChannel:

Randomaccessfile afile = Newrandomaccessfile ("Data/nio-data.txt", "RW"); FileChannel Inchannel =afile.getchannel (); Bytebuffer buf = Bytebuffer.allocate (48); int bytesread = Inchannel.read (BUF), while (bytesread! =-1) {  buf.flip ();  Makes the buffer readable while (buf.hasremaining ()) {     System.out.print (char) buf.get ());//reads one byte at a time  } buf.clear ();  bytesread= Inchannel.read (BUF);} Afile.close ();


Three, selector (Selector)

Selector allows single-threaded processing of multiple channel. If your app has multiple connections (channels) open, but the traffic is low for each connection, it's convenient to use selector. For example, in a chat server.

The benefit of using only a single thread to handle multiple channels is that fewer threads are needed to process the channel. In fact, you can process all the channels with just one thread. For the operating system, context switching between threads is expensive, and each thread consumes some of the system's resources, such as memory. Therefore, the less threads you use, the better.

However, it is necessary to keep in mind that modern operating systems and CPUs are performing more and more well in multitasking, so the overhead of multithreading is getting smaller over time. In fact, if a CPU has multiple cores, not using multitasking may be a waste of CPU power. Anyway, the discussion about that design should be in another different article. Here, it is sufficient to know that using selector can handle multiple channels.

Use one selector to process 3 channel in one single thread using a reproduced diagram:


Creation of Step 1:selector

Create a selector by calling the Selector.open () method, as follows:

Step 2: Register the channel with the selector

In order for channel and selector to be used together to achieve the dream of a single thread handling multiple channels, the channel must be registered on the selector. Can be implemented by the Selectablechannel.register () method, as follows:

Channel.configureblocking (FALSE); Selectionkey key= channel.register (selector, selectionkey.op_read);

Where the first line of code sets the channel to nonblocking mode, and then the second sentence registers the channel with selector. The second parameter of the register () method. This is a "interest collection", meaning what is interesting when listening to the channel through selector. You can listen to four different types of events:

Selectionkey.op_connect

Selectionkey.op_accept

Selectionkey.op_read

Selectionkey.op_write

Special Note: when used with selector, the channel must be in non-blocking mode. This means that FileChannel cannot be used with selector because FileChannel cannot switch to nonblocking mode. Socket channels are available.

Step 3: Block the monitoring channel

once you have registered one or more channels with selector, you can invoke several overloaded select () methods. These methods return those channels that you are interested in (such as connecting, accepting, reading, or writing) that are already ready. In other words, if you are interested in a "read-ready" channel, the Select () method returns those channels where the read event is already ready.  

Here is the Select () method:

int select () int select (long timeout) int Selectnow ()

Select () blocks to at least one channel ready for the event you are registering.

Select (Long Timeout) and select (), in addition to the longest block timeout milliseconds (parameters).

The Selectnow () does not block, and no matter what channel is ready to return immediately (Translator Note: This method performs a non-blocking selection operation.) If no channel becomes selectable since the previous selection operation, this method returns zero directly. )。

Step 4: Traverse the Selectedkeys () Access-ready channel

Once the Select () method is called and the return value indicates that one or more channels are ready, you can then access the Ready channel in the selected keyset (selected key set) by calling selector's Selectedkeys () method. As shown below:

Set Selectedkeys =selector.selectedkeys ();

You can traverse this selected set of keys to access the Ready channel.

Here is an example of a complete combination of channel and selector:

Selector Selector = Selector.open (); Channel.configureblocking (FALSE); Selectionkey key =channel.register (selector, selectionkey.op_read); while (true) {   intreadychannels = Selector.select ();  if (Readychannels = = 0) continue;   Setselectedkeys = Selector.selectedkeys ();  Iterator keyiterator = Selectedkeys.iterator ();  while (Keyiterator.hasnext ()) {    Selectionkey key = Keyiterator.next ();    if (key.isacceptable ()) {        //A connection is accepted by a serversocketchannel.     } else if (key.isconnectable ()) {        //A connection is established with a remote server.     } else if (key.isreadable ()) {        //A channel is ready for reading     }else if (key.iswritable ()) {        //a channel I s ready for writing    }  

selector + Socket channel:

Socket channels include: Socketchannel, Serversocketchannel, and Datagramchannel.

Socketchannel is a channel that is connected to a TCP network socket. There are 2 ways to create:

1) Open a socketchannel and connect to a server on the Internet.

2) Create a socketchannel when a new connection reaches Serversocketchannel.

Serversocketchannel listens for new incoming connections through the Serversocketchannel.accept () method. When the Accept () method returns, it returns a Socketchannel that contains the new incoming connection. Therefore, the accept () method is blocked until a new connection arrives. Datagramchannel is a channel that can send and receive UDP packets. Because UDP is a non-connected network protocol, it cannot be read and written like other channels. It sends and receives a packet.

sets the socket channel and Selector combined because of the multiplexer characteristics of the selector (Event- driven ) and the non-blocking feature of socket channel, it can effectively solve the situation that the high concurrency environment consumes a lot of thread resources for client request processing.

(1) Traditional synchronous blocking IO (network socket programming socket): Each request for the client connection, need to allocate a separate thread for processing, because at any time to monitor whether it has data read and write, and in the data read and write operation, because it is blocking, so even if no data arrives, Will always be blocked waiting. This obviously wastes a lot of CPU and thread resources.

(2) The combination of multiplexed selectors and non-blocking socket channels: Not only can you use a thread to monitor multiple network connections to the client, but when you read and write the data, it returns without blocking if the data is not ready (although in fact the general data is ready once the read and write is performed). So in the case of high concurrency, this approach greatly saves CPU and thread (memory) resources. I can refer to this article for details.

Resources:

1 Http://www.iteye.com/magazines/132-Java-NIO

2 http://www.cnblogs.com/dolphin0520/p/3919162.html

3 http://tutorials.jenkov.com/java-nio/nio-vs-io.html


Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Java Fundamentals: non-blocking IO

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.