Java NIO2: Buffers

Source: Internet
Author: User
Tags comparable

What is a buffer

a Buffer object is a container for a fixed number of data , which acts as a memory, or a segmented transport area where data can be stored and later used for retrieval. Buffers are written and released as discussed in the previous article, there is a buffer class for each non-Boolean raw data type, and although buffers Act on the original data types they store, the buffers are very prone to processing bytes, and non-byte buffers can then be executed in the background from byte or to byte conversions, depending on whether the buffer is How to create the.

the work of the buffer is closely related to the channel . A channel is the entry through which I/O transmissions occur, and buffers are the source or destination of these data transmissions. For a transfer away from the buffer, the data to be passed is placed in a buffer, transmitted to the channel, the transmission of the buffer to be transmitted, and one channel places the data in the provided buffer. This is the key to efficient data processing in buffer data transfer between collaborative objects.

Family tree of the buffer class

is a class-level diagram of buffer. At the top is the universal buffer class, and buffer defines operations that are common to all buffer types, whether they contain data types or specific behaviors that they might have:

Buffer base

Conceptually, a buffer is an array of basic data elements that are wrapped within an object. The advantage of the buffer class over a simple array is that it contains the data content and information about the data in a single object, and the buffer class and its proprietary subclasses define an API to handle the data buffers. Here is a look at the properties and methods that the buffer class has:

1. Properties

All buffers have four properties to provide information about the data elements they contain, which are:

Properties Role
Capacity Capacity, which is the maximum number of data elements that a buffer can hold, which is set when the buffer is created and can never be changed
Limit An upper bound that is the first element in the buffer that cannot be read or written, or, in other words, the count of existing elements in the buffer
Position The position, which is the index of the next element to be read or written, is automatically updated by the corresponding get () and put () functions
Mark tag, which refers to a memo location, call Mark () to set mark=position, call Reset () to set the Postion=mark, the tag is undefined before it is defined

These four properties always follow the following relationships: 0 <= Mark <= position <= limit <= capacity

2. Methods

Here's a look at how to use a buffer, with some of the following methods available in buffer:

Method Role
Object Array () Returns the underlying implementation array for this buffer
int Arrayoffset () Returns the offset of the first buffer disrobed in the underlying implementation array of this buffer
int capacity () Returns the capacity of this buffer
Buffer Clear () Clear this buffer
Buffer Flip () Invert this buffer
Boolean HasArray () Tells if this buffer has an accessible array of underlying implementations
Boolean hasremaining () Tells if there are elements between the current position and the limit
Boolean Isdirect () Tells if this buffer is a direct buffer
Boolean isreadonly () Tells if this buffer is a read-only cache
int limit () Returns the upper bound of this buffer
Buffer limit (int newlimit) Sets the upper bound of this buffer
Buffer Mark () Set the marker in the position of this buffer
int position () Returns the position of this buffer
Buffer position (int newposition) Set the position of this buffer
int remaining () Returns the number of elements between the current position and the upper bound
Buffer Reset () Resets the position of this buffer to the location of the previously marked
Buffer Rewind () To re-orbit this buffer

One thing to note about this API is that functions such as clear () should typically return void instead of buffer references. These functions return references to the objects they are referenced on (this), a class design method that allows cascading calls. Cascading calls allow this type of code:

Buffer.mark (); Buffer.position (5); Buffer.reset () ;

Written by Jane:

Buffer.mark (). Position (5). Reset ();

Buffer Code Instance

To use the buffer, look at the code first, and then explain:

1PublicClassTestmain2{3/**4* String to display5*/6PrivateStatic string[] STRs =7{8 "A Random string value",9 "The product of an infinite number of monkeys",Ten "Hey Hey we ' re The Monkees","Opening Act for the Monkees:jimi Hendrix","Scuse me while I kiss this Fly","Help me! Help me! "14};1516/**17* Subscript index for identifying STRs18*/19PrivateStaticint index = 0;2021st/**22* Place data in buffer23*/24PrivateStaticBooleanFillbuffer (Charbuffer buffer)25{26if (Index >=Strs.length)27ReturnFalse;28String str = strs[index++];30for (int i = 0; I < str.length (); i++)31{32Buffer.put (Str.charat (i));33}3435ReturnTrue;36}3738/**39* Take the data out of buffer40*/41PrivateStaticvoidDrainbuffer (Charbuffer buffer)42{43While(Buffer.hasremaining ())44{45System.out.print (Buffer.get ());46}System.out.println ("");48}4950PublicStaticvoid main (string[] args) 51  {52 charbuffer cb = Charbuffer.allocate (100while (Fillbuffer (CB)) 54  {55  Cb.flip (); 56  Drainbuffer (CB);  Cb.clear () }59 }60}                 

Explain it individually:

1, line 52nd, Charbuffer is an abstract class, it can not be instantiated, so the use of allocate method to instantiate, equivalent to a factory method. The Heapcharbuffer is instantiated, and the default size is 100. According to the class family map of buffer above, you can see that each buffer subclass uses the Allocate method to instantiate the specific subclass, and the instantiation is Heap*buffer.

2, line 24th ~ 36th Row, each take one of the string array, use put method to place a data into Charbuffer

3, line 55th, call the Flip method, which is very important. After the buffer is full, it must be emptied, but if the get () method is now executed directly on the channel, it will remove the undefined data from the useful data we just inserted, and if the position is reset to 0 at this point, the data will be obtained from the correct position. But how do you know when to reach the end of the data we insert? This is the purpose for which the upper bound attribute is introduced----the upper bound attribute indicates the end of the buffer's valid content. So there are two things we need to do to read the data:

(1) Set the upper bound attribute limit to the current position (2) to set the position position to 0

In these two steps, the JDK API gives the developer a FILP () method to complete, and theFlip () method flips a buffer that can continue to add the fill state of the data element to a ready-to-read element's release state , so that each time the element is ready to be read, Must call the Filp () method once

4, line 41st ~ 48th Row, each time first determine whether the buffer has reached the upper bound, if there is the call get () method gets to this element, the get () method will automatically move subscript position

5, line 57th, after the operation of the buffer is complete, call the clear () method to return all properties to the original position, but the clear () method does not alter any data in the buffer

Buffer comparison

The buffer comparison is the Equals method, the buffer comparison is not as simple as we thought, the elements inside the two buffers are equal, and two buffers equal must meet the following three conditions:

1, two object types are the same, buffer containing different data types will never be like, and buffer will never equal a non-buffer object

2, two objects have the same number of elements remaining, the capacity of buffer does not need to be the same, and the index of the remaining data in the buffer does not have to be the same. But the number of remaining elements in each buffer (from position to limit) must be the same

3. The sequence of remaining data elements that should be returned by the Get () function in each buffer must be consistent

Returns False if the above three conditions are not met. The following two images show two equal and unequal buffers, starting with two different buffers that can also be equal:

Then there are two buffers with the same properties but are equal to unequal:

Moving data in bulk

Buffers are designed to be able to transfer data efficiently. Moving one data element at a time is not efficient, as seen in the following list of programs, the buffer API provides a function to bulk move data elements inside and outside the buffer:

PublicAbstractClassCharbufferExtendsBufferImplements Comparable<charbuffer>, Appendable, Charsequence, readable{...Public Charbuffer Get (Char[] DST) {...}Public Charbuffer Get (Char[] DST,int offset,Int length) {...} public final Charbuffer put ( char[] src) {...} public Charbuffer put (char[] src, int offset, int length) {...} public Charbuffer put (Charbuffer src) {...} public final Charbuffer put (String src) {...} public Charbuffer put (String src, int start, int end) {...} ...}               

In fact, the composite effect of this bulk move is the same as the previous one, but these methods can be much more efficient because the buffer implementation can move the data using native code or other optimizations.

byte buffers

The most obvious difference between byte buffers and other buffer types is that they may be the source or target of I/O performed by the channel, and if friends who know about NiO must know that the channel only receives bytebuffer as a parameter.

As we know, the operating system in the memory area for I/O operations, these memory areas, in terms of the operating system, is a contiguous sequence of bytes. Thus, there is no doubt that only byte buffers are eligible to participate in I/O operations. Also recall that the operating system accesses the process directly----in this case the memory space of the JVM process to transfer data. This also means that the target memory area of the I/O operation must be a contiguous sequence of bytes, in which the byte array may not be stored continuously in memory, or the garbage collector may move it at any time. In Java, arrays are objects, and the way data is stored in objects differs from one JVM implementation to another.

For this reason, the concept of a direct buffer is introduced. Direct buffers are used to interact with channels and intrinsic I/O threads by using intrinsic code to tell the operating system to directly release or populate memory areas, maximizing the storage of byte elements in memory areas for direct or original access to the channel.

Direct byte buffers are usually the best choice for I/O operations. In terms of design, they support the most efficient I/O mechanisms available to the JVM, and non-direct byte buffers can be passed to the channel, but this can lead to performance loss, which is often not a target for a local I/O operation. If a developer passes a non-direct Bytebuffer object to a channel for writing, the channel may implicitly do the following in each invocation:

1. Create a temporary direct Bytebuffer object

2. Copy the contents of the non-direct buffer into the temporary buffer

3. Perform low-level I/O operations using temporary buffers

4, temporary buffer object left acting on, and eventually become the garbage collected useless data

This can cause the buffers to replicate on each I/O and produce a large number of objects, something that we are trying to avoid.

Direct buffers are the best choice for I/O, but may cost more than creating non-direct buffers. The memory used by the direct buffer is allocated by calling the local operating system's code, bypassing the standard JVM stack. Creating and destroying a direct buffer is significantly more expensive than a buffer with a stack, depending on the main operating system and the JVM implementation. The memory areas of the direct buffers are not subject to the collection of useless storage units, because they are outside the standard JVM stack.

Direct Bytebuffer is generated by calling the Bytebuffer.allocatedirect () function with the required capacity:

Class Bytebuffer    extendsimplements comparable<bytebuffer>static Bytebuffer Allocatedirect (intnew directbytebuffer (capacity);} ...}      

Java NIO2: Buffers

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.