Now is the turn of Selector. It follows some guidelines about its use. Then some extracts from the API, which I belief are pplaced in the correct order to be more easily understandable. And lastly an example program.
****************************************************************************
The way to go with a Selector is removing the SelectionKey from the
selected set after getting it from the iterator returned by
selectedKeys(). In order to update its interest set before calling select
again call either Selector.register or SelectionKey.interestOps
Do not call SelectionKey.cancel before registering again. Use this
method to cancel the registration definitely. A single
thread should perform the IO activity related with a given Selector, and to update its interests if necessary.
Once a socketChannel is registered with a selector for write we must
delete such interest after the writing operation. Otherwise, because
a socket is almost always writable --unless there were network
congestion and the TCP send buffer is full-- we would find a loop;
because the selector keeps on notifying the availabity to write. Next
time we want to write register that interest again. Either by
SocketChannel.register or by SelectionKey.interestOps
However the read operations do not need to be deregistered after being performed because the selector only notifies when data is available in the channel.
A way to read a non-blocking channel could be:
*************************************************************************
This is summary of the API:
***********************************************************************
Selection Key
A selection key is created each time a channel is registered with a
selector. A key remains valid until it is cancelled by invoking its
cancel method, by closing its channel, or by closing its selector.
Cancelling a key does not immediately remove it from its selector;
it is instead added to the selector's cancelled-key set for removal
during the next selection operation.
A selection key contains two operation sets represented as integer
values:
a) The interest set determines which operation will be
tested for readiness the next time one of the selector's selection
methods is invoked. The interest set is initialized with the value
given when the key is created; it may later be changed via the
interestOps(int) method
b) The ready set identifies the operation categories for which the
key's channel has been detected to be ready by the key's selector.
The ready set is initialized to zero when the key is created. But it
cannot be modified directly.
That a selection key's ready set indicates that its channel is ready for
some operation category is a hint, but not a guarantee, that an
operation in such a category may be performed by a thread without
causing the thread to block. A ready set is most likely to be accurate
immediately after the completion of a selection operation. It is likely
to be made inaccurate by external events and by I/O operations that are
invoked upon the corresponding channel.
The operations of reading and writing the interest set will, in general,
be synchronized with certain operations of the selector. Exactly how is
implementation dependant: In a naive implementation, reading or writing
the interest set may block indefinitely if a selection operation is
already in progress.
cancel()
It synchronizes on the selector's cancelled-key set, and therefore may
block briefly if invoked concurrently with a cancellation or selection
operation involving the same selector.
interestOps()
Whether or not it blocks, and for how long, is implementation-dependent.
interestOps(int)
Whether or not it blocks, and for how long, is implementation-dependent.
**********************************************************************
SelectableChannel
Once registered with a selector, a channel remains registered until it
is deregistered. This involves deallocating whatever resources were
allocated to the channel by the selector.
A channel may be registered at most once with any particular selector.
Newly-created selectable channels are always in blocking mode.
Non-blocking mode is most useful in conjunction with selector-based
multiplexing. A channel must be placed into non-blocking mode before
being registered with a selector, and may not be returned to blocking
mode until it has been deregistered. (It seems that you can place it in
blocking before performing the io operation, and again to non blocking
after it)
SelectionKey register(Selector sel, int ops, Object att)
The key's interest set will have been changed to ops
If this channel is currently registered with the given selector then
the selection key representing that registration is returned.
If this method is invoked while another invocation of this method or of
the configureBlocking method is in progress then it will first block
until the other operation is complete. This method will then synchronize
on the selector's key set and therefore may block if invoked
concurrently with another registration or selection operation involving
the same selector.
**********************************************************************
Selector
A selector maintains three sets of selection keys:
* The key set contains the SelectionKeys representing the current
channel registrations of this selector. This set is returned by the
keys method.
* The selected-key set is the set of keys such that each key's channel
was detected to be ready for at least one of the operations identified
in the key's interest set during a prior selection operation. This set
is returned by the selectedKeys method.
* The cancelled-key set is the set of keys that have been cancelled
but whose channels have not yet been deregistered. This set is not
directly accessible.
A key is added to a selector's key set as a side effect of registering
a channel. The key set itself is not directly modifiable.
Keys are added to the selected-key set by selection operations. A key
may be removed directly from the selected-key set by invoking the set's
remove method or by invoking the remove method of an iterator obtained
from the set. Keys are never removed from the selected-key set in any
other way; they are not, in particular, removed as a side effect of
calls to select(..).
Selection is performed by the select(...), and involves three steps:
1. Each key in the cancelled-key set is removed from each key set of
which it is a member, and its channel is deregistered. This step leaves
the cancelled-key set empty.
2. The underlying operating system is queried for an update as to the
readiness of each remaining channel to perform any of the operations
identified by its key's interest set as of the moment that the
selection operation began. For a channel that is ready for at least
one such operation, one of the following two actions is performed:
1. if the channel's key is not already in the selected-key set then
it is added to that set and its ready-operation set is modified to
identify exactly those operations for which the channel is now
reported to be ready. Any readiness information previously recorded
in the ready set is discarded.
2. Otherwise the channel's key is already in the selected-key set,
so its ready-operation set is modified to identify any new operations
for which the channel is reported to be ready. Any readiness
information previously recorded in the ready set is preserved.
3. If any keys were added to the cancelled-key set while step (2) was
in progress then they are processed as in step (1).
Selectors are themselves safe for use by multiple concurrent threads;
their key sets, however, are not.
The selection operations synchronize on the selector itself, on the key
set, and on the selected-key set, in that order. They also synchronize
on the cancelled-key set during steps (1) and (3) above.
The close method synchronizes on the selector and all three key sets
in the same order as in a selection operation.
Changes made to the interest sets of a selector's keys while a selection
operation is in progress have no effect upon that operation; they will
be seen by the next selection operation.
Keys may be cancelled and channels may be closed at any time.
Hence the presence of a key in one or more of a selector's key sets does
not imply that the key is valid or that its channel is open.
Application code should be careful to synchronize and check these
conditions as necessary if there is any possiblity that another thread
will cancel a key or close a channel.