using java.nio one has to register interest in operations via the SelectableChannel:
SelectionKey = SelectableChannel.register(selector, interestInOpsBitmask)
Registering Interest:
Unregistering Interest:
Are there any pros & cons?
Thanks
Last update: 2021-03-10. The Java NIO Selector is a component which can examine one or more Java NIO Channel instances, and determine which channels are ready for e.g. reading or writing. This way a single thread can manage multiple channels, and thus multiple network connections.
A selector provides a mechanism for monitoring one or more NIO channels and recognizing when one or more become available for data transfer. This way, a single thread can be used for managing multiple channels, and thus multiple network connections.
In NIO we work with channels and buffers. Data is always written from a buffer to a channel and read from a channel to a buffer. Selectors: Java NIO provides the concept of "selectors". It is an object that can be used for monitoring the multiple channels for events like data arrived, connection opened etc.
nio is a non-blocking API for socket connections, which means you are not tight to the number of threads available. With this library, one thread can handle multiple connections at once.
If you always dispatch execution to a thread pool after select() return, you may wish to immediately cancel the key, since you loose the control over the time the Runnable will execute.
Ex.: If you perform the next select() before canceling the previous key (the thread is still waiting for execution), it will be valid yet, causing another thread to carry the already dispatched key. If one of these threads cancels the key, the other will get a CancelledKeyException besides introducing unexpected behavior.
Even if you cancel the key, a thread may register the same channel (update selection keys) before the channel become unregistered (due to your previous key.cancel()
). What, again,
will cause a CancelledKeyException.
To get rid of this trap, you may want to handle events always in the next loop:
while (true) { // true or something less risky
//for each pendingTasks call
pool.execute(task);
Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
key.cancel();
//store dispatch for the next while iteration
pendingTasks.add(task); // do not execute tasks before next select()
}
selector.select(TIMEOUT); // or selectNow if there are
//any pending events to handle.
}
Firt execution will, almost, never return keys, but the select() at the end of your loop MAY guarantee the channel of canceled key be unregistered (bear it's up to your impl) from selector.
However, if you are simply executing a task in the same thread you listen to your selector events, updating sounds easy and safer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With