Java NiO Series Tutorial (vi) Selector

Source: Internet
Author: User
Tags bitwise

Original link Jakob Jenkov Translator: Wander v proofreading: Ding

The Selector (selector) is a component in Java NIO that detects one or more NIO channels and is able to know whether the channel is ready for a read-write event. In this way, a single thread can manage multiple channel to manage multiple network connections.

The following is a list of topics covered in this article:

    1. Why use selector?
    2. Creation of Selector
    3. Registering a channel with the selector
    4. Selectionkey
    5. Channel selection via Selector
    6. WakeUp ()
    7. Close ()
    8. A complete example

Why use selector?

The benefit of using only a single thread to handle multiple channels is that fewer threads are needed to process the channel. In fact, you can process all the channels with just one thread. For the operating system, context switching between threads is expensive, and each thread consumes some of the system's resources, such as memory. Therefore, the less threads you use, the better.

However, it is necessary to keep in mind that modern operating systems and CPUs are performing more and more well in multitasking, so the overhead of multithreading is getting smaller over time. In fact, if a CPU has multiple cores, not using multitasking may be a waste of CPU power. Anyway, the discussion about that design should be in another different article. Here, it is sufficient to know that using selector can handle multiple channels.

The following is an example diagram of a single thread using a selector to process 3 channel:

Creation of Selector

Create a selector by calling the Selector.open () method, as follows:

1 Selector selector = Selector.open();
Registering a channel with the selector

In order to use the channel and the selector, the channel must be registered with the selector. Implemented by the Selectablechannel.register () method, as follows:

1 channel.configureBlocking(false);
2 SelectionKey key = channel.register(selector,
3     Selectionkey.OP_READ);

When used with selector, the channel must be in non-blocking mode. This means that FileChannel cannot be used with selector because FileChannel cannot switch to nonblocking mode. Socket channels are available.

Note the second parameter of the register () method. This is a "interest collection", meaning what is interesting when listening to the channel through selector. You can listen to four different types of events:

    1. Connect
    2. Accept
    3. Read
    4. Write

The channel triggers an event that means that the event is ready. Therefore, a channel successfully connected to another server is called "Ready to connect." A server socket channel is ready to receive new incoming connections called "Receive ready." A data-readable channel can be said to be "read-ready". The channel waiting to write the data can be said to be "write ready".

These four events are represented by the four constants of the Selectionkey:

    1. Selectionkey.op_connect
    2. Selectionkey.op_accept
    3. Selectionkey.op_read
    4. Selectionkey.op_write

If you are interested in more than one event, you can use the bitwise OR operator to concatenate the constants as follows:

1 intinterestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;

The interest collection will continue to be mentioned below.

Selectionkey

In the previous section, when the channel is registered with selector, the Register () method returns a Selectionkey object. This object contains some of the attributes you are interested in:

    • Interest Collection
    • Ready Collection
    • Channel
    • Selector
    • Additional objects (optional)

I'll describe these properties below.

Interest Collection

As described in the section on registering channels with selector, the interest collection is the collection of events of interest that you choose. You can read and write interest collections through Selectionkey, like this:

1 intinterestSet = selectionKey.interestOps();
2
3 booleanisInterestedInAccept  = (interestSet & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT;
4 booleanisInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;
5 booleanisInterestedInRead    = interestSet & SelectionKey.OP_READ;
6 booleanisInterestedInWrite   = interestSet & SelectionKey.OP_WRITE;

As you can see, with the bitwise and action interest collection and given Selectionkey constants, you can determine whether a certain event is in the interest collection.

Ready Collection

The Ready collection is a collection of operations that the channel is already prepared for. After a selection (Selection), you will first access this ready set. The selection will be explained in the next section. You can access the ready collection in this way:

1 intreadySet = selectionKey.readyOps();

You can use methods like the interest collection to detect what events or operations in the channel are ready. However, you can also use the following four methods, all of which return a Boolean type:

1 selectionKey.isAcceptable();
2 selectionKey.isConnectable();
3 selectionKey.isReadable();
4 selectionKey.isWritable();
Channel + Selector

Access to channel and selector from Selectionkey is simple. As follows:

1 Channel  channel  = selectionKey.channel();
2 Selector selector = selectionKey.selector();
Attached objects

You can attach an object or more information to the Selectionkey, which makes it easy to identify a given channel. For example, you can attach a buffer that is used with a channel, or an object that contains aggregated data. Here's how to use it:

1 selectionKey.attach(theObject);
2 Object attachedObj = selectionKey.attachment();

You can also attach objects when registering a channel with the selector using the register () method. Such as:

1 SelectionKey key = channel.register(selector, SelectionKey.OP_READ, theObject);
Channel selection via Selector

Once you have registered one or more channels with selector, you can invoke several overloaded select () methods. These methods return those channels that you are interested in (such as connecting, accepting, reading, or writing) that are already ready. In other words, if you are interested in a "read-ready" channel, the Select () method returns those channels where the read event is already ready.

Here is the Select () method:

    • int Select ()
    • int Select (Long timeout)
    • int Selectnow ()

select()Blocking to at least one channel is ready for your registered event.

select(long timeout)As with select (), except for the longest block of timeout milliseconds (parameters).

selectNow()does not block, no matter what channel is ready to return immediately ( Translator Note: This method performs a non-blocking selection operation.) If no channel becomes selectable since the previous selection operation, this method returns zero directly. ).

The int value returned by the Select () method indicates how many channels are ready. That is, how many channels become ready since the last time the Select () method was called. If the Select () method is called, because a channel becomes ready and returns 1, if the Select () method is called again, it returns 1 again if the other channel is ready. If no action is made on the first ready channel, there are now two ready channels, but only one channel is ready between each select () method call.

Selectedkeys ()

Once the Select () method is called and the return value indicates that one or more channels are ready, you can then access the Ready channel in the selected keyset (selected key set) by calling selector's Selectedkeys () method. As shown below:

1 Set selectedKeys = selector.selectedKeys();

When a Channel is registered like selector, the Channel.register () method returns a Selectionkey object. This object represents the channel registered to the selector. These objects can be accessed through the Selectionkey Selectedkeyset () method.

You can traverse this selected set of keys to access the Ready channel. As follows:

01 Set selectedKeys = selector.selectedKeys();
02 Iterator keyIterator = selectedKeys.iterator();
03 while(keyIterator.hasNext()) {
04     SelectionKey key = keyIterator.next();
05     if(key.isAcceptable()) {
06         // a connection was accepted by a ServerSocketChannel.
07     elseif(key.isConnectable()) {
08         // a connection was established with a remote server.
09     elseif(key.isReadable()) {
10         // a channel is ready for reading
11     elseif(key.isWritable()) {
12         // a channel is ready for writing
13     }
14     keyIterator.remove();
15 }

This loop iterates through each key in the selected key set and detects the ready event for the channel corresponding to each key.

Note the Keyiterator.remove () call at the end of each iteration. Selector does not remove the Selectionkey instance from the selected key set itself. You must remove yourself when you are finished processing the channel. The next time the channel becomes ready, selector will put it in the selected key set again.

The channel returned by the Selectionkey.channel () method needs to be transformed into the type you want to handle, such as Serversocketchannel or Socketchannel.

WakeUp ()

A thread is blocked after invoking the Select () method, and there is a way to return it from the Select () method, even if no channel is ready. Just let the other thread call the Selector.wakeup () method on the object on which the first thread invokes the Select () method. Blocking the line routines on the Select () method immediately returns.

If there are other threads calling the wakeup () method, but no thread is currently blocking on the Select () method, the next thread that calls the Select () method "wakes up" immediately (wake up).

Close ()

Calling its close () method after the selector is exhausted closes the selector and invalidates all Selectionkey instances registered on the selector. The channel itself is not closed.

A complete example

Here is a complete example, open a selector, register a channel to register to this selector (the channel initialization process omitted), and then continuously monitor the selector four kinds of events (accept, connect, read, write) are ready.

01 Selector selector = Selector.open();
02 channel.configureBlocking(false);
03 SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
04 while(true) {
05   intreadyChannels = selector.select();
06   if(readyChannels == 0continue;
07   Set selectedKeys = selector.selectedKeys();
08   Iterator keyIterator = selectedKeys.iterator();
09   while(keyIterator.hasNext()) {
10     SelectionKey key = keyIterator.next();
11     if(key.isAcceptable()) {
12         // a connection was accepted by a ServerSocketChannel.
13     elseif(key.isConnectable()) {
14         // a connection was established with a remote server.
15     elseif(key.isReadable()) {
16         // a channel is ready for reading
17     elseif(key.isWritable()) {
18         // a channel is ready for writing
19     }
20     keyIterator.remove();
21   }
22 }

original articles, reproduced please specify: reproduced from the Concurrent programming network –ifeve.com This article link address: Java NiO Series tutorial (vi) Selector

Java NiO Series Tutorial (vi) Selector

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.