绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
An NIO.2 primer--reference-2
2020-01-06 09:55:40

Asynchronous channel groups

Each asynchronous channel constructed belongs to achannel groupthat shares a pool of Java threads, which are used for handling the completion of initiated asynchronous I/O operations. This might sound like a bit of a cheat, because you could implement most of the asynchronous functionality yourself in Java threads to get the same behaviour, and you'd hope that NIO.2 could be implemented purely using the operating system's asynchronous I/O capabilities for better performance. However, in some cases, it's necessary to use Java threads: for instance, the completion-handler methods are guaranteed to be executed on threads from the pool.

By default, channels constructed with theopen()methods belong to a global channel group that can be configured using the following system variables:

java.nio.channels.DefaultThreadPoolthreadFactory, which defines ajava.util.concurrent.ThreadFactoryto use instead of the default one

java.nio.channels.DefaultThreadPool.initialSize, which specifies the thread pool's initial size

Three utility methods injava.nio.channels.AsynchronousChannelGroupprovide a way to create new channel groups:

withCachedThreadPool()

withFixedThreadPool()

withThreadPool()

These methods take either the definition of the thread pool, given as ajava.util.concurrent.ExecutorService, or ajava.util.concurrent.ThreadFactory. For example, the following call creates a new channel group that has a fixed pool of 10 threads, each of which is constructed with the default thread factory from theExecutorsclass:

AsynchronousChannelGroup tenThreadGroup =

AsynchronousChannelGroup.withFixedThreadPool(10, Executors.defaultThreadFactory());

The three asynchronous network channels have an alternative version of theopen()method that takes a given channel group to use instead of the default one. For example, this call tellschannelto use thetenThreadGroupinstead of the default channel group to obtain threads when required by the asynchronous operations:

AsynchronousServerSocketChannel channel =

AsynchronousServerSocketChannel.open(tenThreadGroup);

Defining your own channel group allows finer control over the threads used to service the operations and also provides mechanisms for shutting down the threads and awaiting termination. Listing 3 shows an example:

Listing 3. Controlling thread shutdown with a channel group

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

}

if (!tenThreadGroup.isTerminated()) {

// forcibly shutdown, the channel will be closed and the accept will abort

tenThreadGroup.shutdownNow();

}

// the group should be able to terminate now, wait for a maximum of 10 seconds

tenThreadGroup.awaitTermination(10, TimeUnit.SECONDS);

TheAsynchronousFileChanneldiffers from the other channels in that, in order to use a custom thread pool, theopen()method takes anExecutorServiceinstead of anAsynchronousChannelGroup.

 

Asynchronous datagram channels and multicasting

The final new channel is theAsynchronousDatagramChannel. It's similar to theAsynchronousSocketChannelbut worth mentioning separately because the NIO.2 API adds support for multicasting to the channel level, whereas in NIO it is only supported at the level of theMulticastDatagramSocket. The functionality is also available injava.nio.channels.DatagramChannelfrom Java 7.

AnAsynchronousDatagramChannelto use as a server can be constructed as follows:

AsynchronousDatagramChannel server = AsynchronousDatagramChannel.open().bind(null);

Next, we set up a client to receive datagrams broadcast to a multicast address. First, we must choose an address in the multicast range (from 224.0.0.0 to and including 239.255.255.255), and also a port that all clients can bind to:

// specify an arbitrary port and address in the range

int port = 5239;

InetAddress group = InetAddress.getByName("226.18.84.25");

We also require a reference to which network interface to use:

// find a NetworkInterface that supports multicasting

NetworkInterface networkInterface = NetworkInterface.getByName("eth0");

Now, we open the datagram channel and set up the options for multicasting, as shown in Listing 4:

Listing 4. Opening a datagram channel and setting multicast options

// the channel should be opened with the appropriate protocol family,

// use the defined channel group or pass in null to use the default channel group

AsynchronousDatagramChannel client =

AsynchronousDatagramChannel.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 datagrams

client.setOption(StandardSocketOption.IP_MULTICAST_IF, networkInterface);

The client can join the multicast group in the following way:

MembershipKey key = client.join(group, networkInterface);

Thejava.util.channels.MembershipKeyis a new class that provides control over the group membership. Using the key you can drop the membership, block and unblock datagrams from certain addresses, and return information about the group and channel.

The server can then send a datagram to the address and port for the client to receive, as shown in Listing 5:

Listing 5. Sending and receiving a datagram

// 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 receiving datagram");

e.printStackTrace();

}

});

Multiple clients can also be created on the same port and joined to the multicast group to receive the datagrams sent from the server.

 

Conclusion

NIO.2's asynchronous channel APIs provide a convenient and standard way of performing asynchronous operations platform-independently. They allow application developers to write programs that use asynchronous I/O in a clear manner, without having to define their own Java threads and, in addition, may give performance improvements by using the asynchronous support on the underlying OS. As with many Java APIs, the amount that the API can exploit an OS's native asynchronous capabilities will depend on the support for that platform.

Part 2: The file system APIs

This article completes our two-part introduction to More New I/O APIs for Java (NIO.2) in Java 7. Like the asynchronous channel APIs explored inPart 1, NIO.2's file system APIs fill some significant gaps in the way previous Java versions handle I/O. According to the NIO.2 Java specification request (JSR 203):

The Java platform has long needed a filesystem interface better than thejava.io.Fileclass. That class does not handle filenames in a way that works consistently across platforms, it does not support efficient file-attribute access, it does not allow sophisticated applications to take advantage of filesystem-specific features (for example, symbolic links) when available, and many of its methods simply return false on error instead of throwing an informative exception.

Coming to the rescue are three new file system packages in the Java 7 beta:

java.nio.file

java.nio.file.attribute

java.nio.file.spi

This article focuses on the most useful classes in these packages:

java.nio.file.Filesandjava.nio.file.FileVisitorallow you to walk through file systems, querying files or directories up to a certain depth and executing user-implemented callback methods for each one found.

java.nio.file.Pathandjava.nio.file.WatchServiceallow you to register to "watch" a specific directory. An application watching directories receives notification if files in those directories are created, modified, or deleted.

java.nio.attribute.*AttributeViewallow you to view file and directory attributes that were previously hidden from Java users. These attributes include file owner and group permissions, access-control lists (ACLs), and extended file attributes.

We'll provide examples that show how to use these classes. The examples are available in a runnable state (seeDownload), and you can try them out on the Java 7 betas available from IBM® and Oracle (both still under development at the time of this writing; seeResources).

File visitors

分享好友

分享这个小栈给你的朋友们,一起进步吧。

JAVA玩具小屋
创建时间:2019-08-16 16:54:49
分享程序开发方面的小经验,思考一些比较简单易懂的技术问题
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • Yios5092
    栈主

小栈成员

查看更多
  • 栈栈
  • coyan
  • 25minutes
  • ?
戳我,来吐槽~