Asynchronous ChannelProvides connections that support connections, reads, writes, and other non-lock operations, and provides control mechanisms for started operations. More new I/O APIs for Java platform (nio.2) in Java 7. NIO. added four asynchronous channels to the channels package, enhancing the new I/O APIs (NIO) in Java 1.4 ):
- Asynchronoussocketchannel
- Asynchronousserversocketchannel
- Asynchronousfilechannel
- Asynchronousdatagramchannel
These classes are similar in style to NiO channel APIs. They share the same method and parameter struct, and most parameters available for the NIO channel class are still available for new asynchronous versions. The main difference is that the new channel enables asynchronous execution of some operations.
The asynchronous channel API provides two monitoring and control mechanisms for started asynchronous operations. The first method is to return a java. util. Concurrent. Future object, which will model a pending operation and can be used to query its status and obtain results. The second is to pass the operation to a new class object, java. NiO. channels. completionhandler, which defines the processing after the operation is completed. Program Method. Each asynchronous channel class defines API copies for each operation, so any mechanism can be used.
In this article Two-part seriesArticle In section 1, we introduce each channel and provide some simple examples to demonstrate how to use them. These examples are all running (see Download ), You can be in Oracle and IBM (both in the development phase during the writing of this Article; see See Materials . In Part 2 , You will have the opportunity to understand the nio.2 file system API.
Asynchronous socket channel and features
First, we will understand the asynchronousserversocketchannel and asynchronoussocketchannel classes. The first example we will see shows how to use these new classes to implement simple clients/servers. Step 1: Set the server.
Set Server
Open asychronousserversocketchannel and bind it to an address similar to serversocketchannel:
Asynchronousserversocketchannel Server = Asynchronousserversocketchannel. open (). BIND (null ); |
Method BIND () uses a socket address as its parameter. The convenient way to find the idle port is to pass a null address, which will automatically bind the socket to the local host address and use the idleTemporaryPort.
Next, you can tell the channel to accept a connection:
Future <asynchronoussocketchannel> acceptfuture = server. Accept (); |
This is the first difference from NiO. An accepted call always returns immediately, and -- different from serversocketchannel. accept (), which returns a socketchannel -- it returns a future <asynchronoussocketchannel> object, which can be used to retrieve asynchronoussocketchannel later. The generic type of the future object is the result of actual operations. For example, the read or write operation returns a future <integer> because of the number of read or write bytes.
Using the future object, the current thread can be blocked to wait for the result:
Asynchronoussocketchannel worker = Future. Get (); |
Here, the blocking timeout is 10 seconds:
Asynchronoussocketchannel worker = Future. Get (10, timeunit. Seconds ); |
Or the current status of the Round-Robin operation can also be canceled:
If (! Future. isdone ()){ Future. Cancel (true ); } |
The cancel () method can use a Boolean sign to indicate whether the thread that the execution accepts can be interrupted. This is a useful enhancement. In earlier Java versions, you can only disable sockets to stop such blocking I/O operations.
Client settings
Next, you need to enable and connect to the asynchronoussocketchannel between the server and set the client:
Asynchronoussocketchannel client = asynchronoussocketchannel. open (); Client. Connect (server. getlocaladdress (). Get (); |
Once the client is connected to the server, you can use the byte cache channel to perform read and write operations, as shown in Listing 1:
Listing 1. Using read/write bytes Cache
// Send a message to the server Bytebuffer message = bytebuffer. Wrap ("ping". getbytes ()); Client. Write (Message). Get ();// Read a message from the client Worker. Read (readbuffer). Get (10, timeunit. Seconds ); System. Out. println ("message:" + new string (readbuffer. Array ())); |
It also supports asynchronous distributed read and write operations, which require a large number of bytes to be cached.
The API of the new asynchronous channel is completely extracted from the underlying socket: the socket cannot be directly obtained, but previously socket () can be called, for example, socketchannel. Two new methods -- getoption and setoption -- are introduced to query and set socket options in the Asynchronous Network Channel. For example, you can retrieve the received cache size through channel. getoption (standardsocketoption. so_rcvbuf) instead of channel. socket (). getreceivebuffersize.
Process completion
The future object substitution mechanism is used to register a callback to an asynchronous operation. The completionhandler interface has two methods:
- Void completed (V result, a attachment) is executed when the task completion result contains a Type V.
- Void failed (throwable E, A attachment) is executed when the task fails due to throwable E.
The attachment parameters of both methods are an object passed to the asynchronous operation. If the same object is used for multiple operations, it can be used to track which operation has been completed.
Open command
Let's look at an example of using the asynchronousfilechannel class. You can create a new channel by passing the java. NiO. file. Path object to the static open () method:
Asynchronousfilechannel filechannel = asynchronousfilechannel. Open (paths. Get ("myfile ")); |
the new open command used for filechannel the format of the open command used for asynchronous channel has been transplanted to the filechannel class. In NiO, The filechannel is obtained by calling getchannel () on fileinputstream, fileoutputstream, or randomaccessfile. With nio.2, you can use the open () method to directly create a filechannel. The related examples are shown here.
PATH is a new class in Java 7.Part 1To find more details. You can use the paths. Get (string) utility to create a path from the string representing the file name.
By default, the file is opened for reading. The open () method can use additional options to specify how to open the file. For example, this call opens a file for reading or writing. If necessary, the file will be created and the file will be deleted when the channel is closed or the JVM is terminated:
Filechannel = asynchronousfilechannel. Open (paths. Get ("afile "), Standardopenoption. Read, standardopenoption. Write, Standardopenoption. Create, standardopenoption. delete_on_close ); |
alternative method: open () provides better control over the channel and allows you to set file attributes.
implement a processing program
next, you can write these files and perform some operations after writing them. First, construct a completionhandler that encapsulates "something", as shown in Listing 2:
List 2. process created
completionhandler handler = New completionhandler () { @ override Public void completed (integer result, object attachment) { system. out. println (Attachment + "completed with" + Result + "bytes written"); }< BR >@override Public void failed (throwable E, object attachment) { system. err. println (Attachment + "failed with:"); E. printstacktrace (); }< BR >}; |
Now you can write:
Filechannel. Write (bytebuffer. Wrap (bytes), 0, "write operation 1", Handler ); |
Use the write () method:
- Bytebuffer that contains the content to be written
- Absolute position in the file
- Attachment object to be passed to the completion handler Method
- Process completion
The operation must provide an absolute position in the file to be read or written. The file has an internal location mark to indicate the location where the read/write operation occurred. This is meaningless because a new operation can be started before the previous operation is completed, their order of occurrence cannot be guaranteed. For the same reason, there is no method in asynchronousfilechannel API for setting or querying the location, and there is no method in filechannel.
In addition to the read/write method, the asynchronous locking method is also supported. Therefore, if there are other threads holding the lock timing, you can execute the access lock on the file, instead of locking in the current thread (or using trylock for polling ).
Asynchronous Channel group
Each asynchronous channel belongs to oneChannel groupThey share a Java thread pool, which is used to complete the asynchronous I/O operations started. This looks a bit like spoofing, because you can execute most asynchronous functions in your own Java thread to achieve the same performance, and, you may want to use the asynchronous I/O capability of the operating system to execute nio.2 for better performance. However, in some cases, it is necessary to use a Java thread: for example, ensure that the completion-handler method is executed on the thread from the thread pool.
By default, a channel with the open () method belongs to a global channel group and can be configured using the following system variables:
- Java. NiO. channels. defaultthreadpoolthreadfactory. Instead of using the default settings, it defines a java. util. Concurrent. threadfactory
- Java. NiO. channels. defaultthreadpool. initialsize, specifies the initial size of the thread pool
Three practical methods in Java. NiO. channels. asynchronouschannelgroup provide methods to create a new channel group:
- Withcachedthreadpool ()
- Withfixedthreadpool ()
- Withthreadpool ()
These methods can also be defined for thread pools, such as Java. util. Concurrent. executorservice or Java. util. Concurrent. threadfactory. For example, the following call creates a new channel group with a thread pool. The thread pool contains 10 threads, each of which is constructed as a thread factory from the executors class:
Asynchronouschannelgroup tenthreadgroup = Asynchronouschannelgroup. withfixedthreadpool (10, executors. defaultthreadfactory ()); |
All three Asynchronous Network channels have an alternative version of the open () method. They use the given Channel group instead of the default Channel group. For example, when an Asynchronous Operation Request occurs, this call tells the channel to use tenthreadgroup instead of the default Channel group to obtain the thread:
Asynchronousserversocketchannel = Asynchronousserversocketchannel. Open (tenthreadgroup ); |
define your own channel Group to better control the threads serving the operation, and provide a mechanism to close the thread or wait for termination. Listing 3 shows related examples:
listing 3. Using channel groups to control thread shutdown
// first initiate a call that won't be satisfied channel. accept (null, completionhandler); // once the operation has been set off, the channel group can // be used to control the shutdown If (! Tenthreadgroup. isshutdown () { // once the group is shut down no more channels can be created with it tenthreadgroup. shutdown (); }< br> If (! Tenthreadgroup. isterminated () { // forcibly shutdown, the channel will be closed and the accept will abort tenthreadgroup. shutdownnow (); }< br> // The Group shocould be able to terminate now, wait for a maximum of 10 seconds tenthreadgroup. awaittermination (10, timeunit. seconds); |
Asynchronousfilechannel is different from other channels here. To use a custom thread pool, the open () method adopts executorservice instead of asynchronouschannelgroup.
Asynchronous datagram channel and Multicast
The last new channel is asynchronousdatagramchannel. It is similar to asynchronoussocketchannel, but because the nio.2 API adds support for multicast at this channel level, this support is provided only at the multicast1_ramsocket level in NIO, therefore, it is necessary to propose it separately. Java. NiO. channels. initramchannel in Java 7 can also provide this function.
Asynchronousdatagramchannel used as a server can be constructed as follows:
Asynchronousdatagramchannel Server = asynchronousdatagramchannel. open (). BIND (null ); |
Next, you can set the client to receive the datagram broadcast sent to a multicast address. First, you must select an address (from 224.0.0.0 to 239.255.255.255) within the multicast address range, and select a port that can be bound to all clients:
// Specify an arbitrary port and address in the range Int Port = 5239; Inetaddress group = inetaddress. getbyname ("226.18.84.25 "); |
We also need a reference to the network interface used:
// Find a networkinterface that supports Multicasting Networkinterface = networkinterface. getbyname ("eth0 "); |
Now open the datagram channel and set multicast options, as shown in Listing 4:
Listing 4. Open the datagram channel and set multicast options
// The channel shoshould be opened with the appropriate protocol family, // use the defined Channel group or pass in null to use the default Channel group asynchronous?ramchannel client = asynchronous=ramchannel. open (standardprotocolfamily. inet, tenthreadgroup); // enable binding multiple sockets to the same address client. setoption (standardsocketoption. so_reuseaddr, true); // bind to the port client. BIND (New inetsocketaddress (port); // set the interface for sending multicast rams client. setoption (standardsocketoption. ip_multicast_if, networkinterface); |
The client can join multicast groups as follows:
Membershipkey key = client. Join (group, networkinterface ); |
Java. util. channels. membershipkey is a new class that provides Group member control. With this key, you can discard group members, block or cancel blocking datagram from a specific address, and return messages about groups and channels.
The server can send a datagram to a specific address and port for receiving by the client, as shown in listing 5:
Listing 5. send and receive data packets
// Send message Bytebuffer message = bytebuffer. Wrap ("hello to all listeners". getbytes ()); Server. Send (message, new inetsocketaddress (group, Port )); // Receive message Final bytebuffer buffer = bytebuffer. Allocate (100 ); Client. Receive (buffer, null, new completionhandler <socketaddress, Object> (){ @ Override Public void completed (socketaddress address, object attachment ){ System. Out. println ("Message from" + address + ":" + New String (buffer. Array ())); } @ Override Public void failed (throwable E, object attachment ){ System. Err. println ("error processing ing datasync "); E. printstacktrace (); } }); |
You can create multiple clients on the same port and add them to multicast groups to receive data from the server.
Conclusion
The asynchronous channel APIs of nio.2 provides a convenient and platform-independent standard method for performing asynchronous operations. This allows application developers to write programs in a clearer way, without having to define their own Java threads, you can also use the asynchronous functions supported by the underlying OS to improve performance. Like other Java APIs, the number of OS self-owned asynchronous functions that an API can use depends on its support for the platform.
This article is transferred from www.35java.com