NiO and Io (RPM)

Source: Internet
Author: User
Tags rewind

Java NIO consists of the following core components:

    • Channels (channel)
    • Buffers (buffer)
    • Selectors (selector)
    • Other

Channel and Buffer:

All IO re-NIO starts with a channel. The channel is a bit like a stream, the data can be read from the channel to buffer, or it can be written from buffer to the channel:

The main implementations of the channel are as follows:

    • FileChannel
    • Datagramchannel
    • Socketchannel
    • Serversocketchannel

These channels cover both UDP and TCP network IO

The implementation of buffer:

    • Bytebuffer
    • Charbuffer
    • DoubleBuffer
    • Floatbuffer
    • Intbuffer
    • Longbuffer
    • Shortbuffer

These buffer covers the basic data types sent over Io (JAVA NiO also has a mappedbytebuffer, which represents a memory-mapped file)

Selector

Selector allows single-threaded processing of multiple channels, and if your app opens multiple connections (lanes), each connection has a low traffic, and using selector is convenient, such as in a chat server. For example, a selector dealing with 3 channel issues

With selector, you have to register the channel with selector and then call its select (), which blocks until a registered channel event is ready. Once this method returns, the thread can handle these events, and the example of the event is the new connection, the data reception, and so on.

Java NIO vs. IO
When should I use IO and when do I use NIO? In this article, I'll try to clearly parse the differences between Java NiO and Io, their usage scenarios, and how they affect your code design.

The following table summarizes the main differences between Java NiO and Io, and I'll describe in more detail the differences in each section of the table.

Io Nio
Stream oriented Buffer oriented
Blocking IO Non Blocking IO
Selectors

Stream-oriented and buffer-oriented

The biggest difference between Java NiO and Io is thatIO is stream-oriented, and NIO is buffer- oriented. The Java IO-oriented stream means that one or more bytes are read every time from the stream 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 ya Xu moves the data read from the stream before and after it, it needs to be cached to a buffer first. Java NiO has a slightly different buffer-oriented approach, and the data is read to a buffer that it processes later, moving back and forth in the buffer as needed, which increases the flexibility of the process, but also checks whether the buffer contains all the data you need to process, and You need to 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, which means that when a thread calls read () or write (), the thread is blocked until some data is read, or the data is fully written, and the thread cannot do anything else during this time. the non-blocking mode of Java NiO enables a thread to send a request to read data from a channel, but it can only get the data currently available, and if no data is available, nothing is obtained. Instead of keeping the thread blocked, all until the data becomes readable, The thread can continue to do other things, non-blocking writes as well, a thread requests hill some data to the channel, but does not need to wait for it to be fully written, this thread can do something else at the same time, the thread of the same city will be non-blocking IO idle time for other channels to perform IO operations, So a single thread can now manage multiple input and output channels.

Selector (selectors)

selectors allow a single thread to listen to multiple input channels , you can register multiple channels using a selector, and then use a separate thread to "select" the channel: there are already inputs that can be processed in these channels, or select the channels that are ready to be written. This mechanism of selection, Makes it easy for a single thread to manage multiple channels.

How NiO and Io affect the design of applications

    • Call to the NIO or IO class API (IO reads verbatim from a InputStream, NIO is the data must be read into the buffer before processing)
    • Data processing
    • The number of threads used to process the data

Data Processing

Data processing is also affected by the use of purely nio designs compared to IO designs.

In the IO design, we read data byte by bit from InputStream or reader. Let's say you're working on a line-based text stream, for example:

Code
Name:anna  age:25  Email: [Email protected]  phone:1234567890  

The flow of this line can be handled like this:

Java code

InputStream input = ...; Get the InputStream from the client socket  BufferedReader reader = new BufferedReader (new InputStreamReader (input)) ;        String nameline   = Reader.readline ();  String AgeLine    = Reader.readline ();  String emailline  = Reader.readline ();  String phoneline  = Reader.readline ();  


Note how long the processing status is determined by the program execution. In other words, once the Reader.readline () method returns, you know that the text line is read and readLine () blocks until the entire line is read, which is why. You also know that this row contains the name; again, the second readline () call returns, and you know that this line contains age. As you can see, the handler runs only when new data is read, and knows what the data is for each step. Once a running thread has processed some of the data that is being read, the thread will no longer roll back the data (mostly so). It also illustrates this principle:


Read data from a blocked stream



And the implementation of a NIO will be different, here is a simple example:

Java code
Bytebuffer buffer = bytebuffer.allocate ($);  int bytesread = inchannel.read (buffer);  


Note the second line, which reads bytes from the channel to Bytebuffer. When this method call returns, you do not know whether all the data you need is in the buffer. What you know is that the buffer contains some bytes, which makes handling a bit difficult.
Assuming that after the first read (buffer) call, the data that is read into the buffer is only half a line, for example, "Name:an", can you process the data? Obviously, there is no need to wait until the entire row of data is read into the cache, before any processing of the data is meaningless.

So, how do you know if the buffer contains enough data to handle it? Well, you don't know. The found method can only view the data in the buffer. The result is that you have to check the buffer data several times before you know that all the data is in the buffer. This is not only inefficient, but also can make the program design scheme messy. For example:

Java code
Bytebuffer buffer = bytebuffer.allocate ($);      int bytesread = inchannel.read (buffer);      while (! bufferfull (Bytesread)) {      bytesread = inchannel.read (buffer);  }  


The Bufferfull () method must keep track of how much data is read into the buffer and return TRUE or false, depending on whether the buffer is full. In other words, if the buffer is ready to be processed, it means that the buffer is full.

The Bufferfull () method scans the buffer, but must remain the same state before the Bufferfull () method is called. If not, the next data read into the buffer may not read to the correct location. This is not possible, but it is another problem to be aware of.

If the buffer is full, it can be processed. If it is dissatisfied and is meaningful in your actual case, you may be able to handle some of the data. But in many cases this is not the case. Shows "buffer Data Loop Ready":


Read the data from one channel until all the data is read into the buffer.



Summarize

NIO allows you to manage multiple channels (network connections or files) using only one (or several) single threads, but the cost is that parsing data can be more complex than reading data from a blocking stream.

If you need to manage thousands of connections that are open at the same time, these connections can only send a small amount of data, such as a chat server, to implement NIO's servers as an advantage. Similarly, if you need to maintain many open connections to other computers, such as a peer-to network, using a separate thread to manage all your outbound connections may be an advantage. The design of multiple connections for a thread is as follows:


Single thread to manage multiple connections



If you have a small number of connections that use very high bandwidth and send a large amount of data at once, perhaps a typical IO server implementation might be very fit. Illustrates a typical IO server design:


A typical IO server design: A connection is handled by a thread

Channel (Channels)

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

    • The data can be read from the channel, and the data can be written to the channel. But stream reads and writes are usually one-way.
    • Channels can be read and written asynchronously.
    • The data in the channel is always read to a buffer first, or it is always written from a buffer.

As mentioned above, the data is read from the channel to the buffer, and the data is written from the buffer to the channel. As shown in the following:



The implementation of channel

These are the most important implementations of the channel in Java NIO:

    • FileChannel: Read and write data from a file.
    • Datagramchannel: Can read and write data on the network through UDP.
    • Socketchannel: Data in the network can be read and written through TCP.
    • Serversocketchannel: You can listen for incoming TCP connections, like Web servers. A socketchannel is created for each new incoming connection.

Basic Channel Example

The following is an example of using FileChannel to read data into buffer:

Java code
    Randomaccessfile afile = new Randomaccessfile ("Data/nio-data.txt", "RW");      FileChannel Inchannel = Afile.getchannel ();            Bytebuffer buf = Bytebuffer.allocate ();            int bytesread = Inchannel.read (BUF);      while (bytesread! =-1) {            System.out.println ("Read" + bytesread);      Buf.flip ();            while (Buf.hasremaining ()) {      System.out.print (char) buf.get ());      }            Buf.clear ();      Bytesread = Inchannel.read (BUF);      }      Afile.close ();  


Note that the call to Buf.flip () first reads the data into buffer, then inverts the buffer, and then reads the data from buffer. Further details of the buffer are explained in the next section.

Buffer (buffer)

Basic usage of buffer

Reading and writing data using buffer typically follows these four steps:

    1. Write data to Buffer
    2. Calling flip() methods
    3. reading data from buffer
    4. Calling a clear() method or compact() method

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.

Here is an example of using buffer:

Randomaccessfile afile = new Randomaccessfile ("Data/nio-data.txt", "RW"); FileChannel Inchannel = Afile.getchannel ();//create buffer with capacity of bytesbytebuffer buf = Bytebuffer.allocate (4 8); int bytesread = Inchannel.read (BUF); Read into Buffer.while (bytesread! =-1) {  buf.flip ();  Make buffer ready for read  while (buf.hasremaining ()) {      System.out.print (char) buf.get ());//read 1 byte at a ti Me  }  buf.clear ();//make buffer ready for writing  bytesread = Inchannel.read (BUF);} Afile.close ();

Capacity,position and limit for buffer

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.

To understand how the buffer works, you need to familiarize yourself with its three properties:

    • Capacity
    • Position
    • Limit

The meaning of position and limit depends on whether the buffer is in read or write mode. No matter what mode the buffer is in, the meaning of capacity is always the same.

Here is a description of the capacity,position and limit in the read-write mode, explained in detail behind the illustration.

Capacity

As a block of memory, buffer has a fixed size value, also known as "capacity". You can only write in capacity a byte, Long,char and other types. Once the buffer is full, it needs to be emptied (by reading the data or clearing the data) to continue writing the data.

Position

When you write data into buffer, position represents the current position. The initial position value is 0. When a byte, long, and other data is written to buffer, the position moves forward to the next buffer cell that can insert the data. The position can be capacity–1 maximum.

When reading data, it is also read from a specific location. When the buffer is switched from write mode to read mode, the position is reset to 0. When the data is read from the position in buffer, the position moves forward to the next readable position.

Limit

In write mode, the limit of buffer indicates how much data you can write to buffer. Write mode, limit equals buffer's capacity.

When you switch buffer to read mode, limit indicates how much data you can read. Therefore, when you toggle buffer to read mode, limit is set to the position value in write mode. In other words, you can read all the previously written data (limit is set to the number of written data, this value is position in write mode)

Type of buffer

Java NIO has the following buffer types

    • Bytebuffer
    • Mappedbytebuffer
    • Charbuffer
    • DoubleBuffer
    • Floatbuffer
    • Intbuffer
    • Longbuffer
    • Shortbuffer

P<>
As you can see, these buffer types represent different data types. In other words, the bytes in the buffer can be manipulated by a char,short,int,long,float or double type.

Mappedbytebuffer is a bit special, in the specialized chapters that cover it.

Allocation of buffer

To get a buffer object, you first need to allocate it. Each buffer class has a allocate method. The following is an example of a bytebuffer that allocates 48 bytes of capacity.

1 ByteBuffer buf = ByteBuffer.allocate(48);

This is the assignment of a charbuffer that can store 1024 characters:

1 CharBuffer buf = CharBuffer.allocate(1024);
Write data to Buffer

There are two ways of writing data to buffer:

    • Write from channel to buffer.
    • Write to buffer by using the put () method in buffer.

Example of writing from channel to buffer

1 intbytesRead = inChannel.read(buf); //read into buffer.

Example of buffer written by the Put method:

1 buf.put(127);

There are many versions of the Put method that allow you to write data to buffer in different ways. For example, write to a specified location, or write a byte array to buffer. More details on buffer implementations refer to Javadoc.

Flip () method

The flip method switches buffer from write mode to read mode. Calling the flip () method resets position back to 0 and sets the limit to the value of the previous position.

In other words, position is now used to mark the read position, and limit indicates how many bytes, char, and so on have been written before--how many bytes, char, and so on can now be read.

reading data from buffer

There are two ways of reading data from buffer:

    1. Reads data from buffer to channel.
    2. Use the Get () method to read data from buffer.

Example of reading data from buffer to channel:

1 //read from buffer into channel.
2 intbytesWritten = inChannel.write(buf);

Example of using the Get () method to read data from buffer

1 byteaByte = buf.get();

The Get method has many versions that allow you to read data from buffer in different ways. For example, reading from a specified position, or reading data from buffer to a byte array. More details on buffer implementations refer to Javadoc.

Rewind () method

Buffer.rewind () sets the position back to 0, so you can reread all the data in the buffer. The limit remains unchanged and still indicates how many elements (Byte, char, and so on) can be read from the buffer.

Clear () and compact () methods

Once you have finished reading the data in buffer, you need to make buffer ready to be written again. Can be done through the clear () or compact () method.

If the call is the clear () method, position will be set back to the value 0,limit to capacity. In other words, Buffer is emptied. The data in buffer is not cleared, but these tags tell us where we can start writing data to buffer.

If there are some unread data in buffer and the clear () method is called, the data will be "forgotten", meaning no more tags will tell you what data has been read or not.

If you still have unread data in buffer and you need that data later, but you want to write some data first, use the compact () method.

The Compact () method copies all unread data to the beginning of the buffer. The position is then set to the last unread element just behind it. The Limit property is still set to capacity, just like the clear () method. Now buffer is ready to write the data, but it will not overwrite the unread data.

Mark () and Reset () method

By calling the Buffer.mark () method, you can mark a specific position in buffer. You can then revert to this position by calling the Buffer.reset () method. For example:

1 buffer.mark();
2
3 //call buffer.get() a couple of times, e.g. during parsing.
4
5 buffer.reset();  //set position back to mark.
Equals () and CompareTo () methods

You can use the Equals () and CompareTo () methods two buffer.

Equals ()

Two buffer equals when the following conditions are met:

    1. Have the same type (byte, char, int, and so on).
    2. The remaining number of Byte, char, and so on in buffer is equal.
    3. All remaining byte, char, and so on in buffer are the same.

As you can see, equals is just a part of the comparison buffer, not every element in it is compared. In fact, it compares only the remaining elements in buffer.

CompareTo () method

The CompareTo () method compares the remaining elements of two buffer (byte, char, and so on) and considers a buffer "less than" another buffer if the following conditions are true:

    1. The first unequal element is smaller than the corresponding element in the other buffer.
    2. All elements are equal, but the first buffer is exhausted before the other (the number of elements in the first buffer is less than the other one).

(Note: The remaining elements are elements from position to limit)

NiO and Io (RPM)

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.