NIO selector Selector
In the last of further in-depth in JAVA NIO we learned how to use Buffer
, but in Java NIO in the IO and we learned a little Channel
of the concept, we know that Channel
just like mined the tracks, Buffer
just like mine car on the tracks for data operations are for real Buffer
operations. And there is a very important concept in the NIO Selector
, it is like mined in the same scheduling system.
Why should Selector
To understand why there must Selector? This question, we first have to know that there are five I / O model on UNIX systems: synchronous blocking I / O, non-blocking synchronous I / O, I / O multiplexing, signal driven I / O and asynchronous I / O . The several I / O model is what does that mean, what about metaphor.
- Blocking I / O model: a man fishing when the fish did not bite, and so on has been sitting on the shore.
- Non-blocking I / O model: while fishing play phone, and then see if there will be every fish hook, any quickly pull rod.
- I / O multiplexing model: put a bunch of fishing rod, on the shore have been guarding the pile of fishing rod, not a fish bites on the play phone.
- Signal-driven I / O model: tied a cowbell on the fishing rod, when the bell rang, I know the fish hook, you can then concentrate on playing mobile phone.
- Asynchronous I / O model: hire someone to give me a fish, give me to the residence after the catch, I Why Why.
Blocking and non-blocking refers to the application when initiating I / O operation is returned immediately or wait. Asynchronous and synchronized means that the application core communications, data from the copy of the application space to the kernel space, is initiated or triggered by the core by the application.
The so-called I / O is the data copy process between the computer memory and an external device , we know that the CPU speed is much higher than the external memory access apparatus, so the CPU is usually the first read data to the external memory device, and and then processed. Then there is a scene at this time, that when your user program sends a read command to the external device through the CPU, data from the external memory device to take some time, then the CPU is the rest of it at this time? Or to others? Or constantly asked to do? Reached? Reached……? This is the problem I / O model to be solved.
Our NIO analog I / O model is the I / O multiplexing model. By blocking only Selector
this one thread, by Selector
constantly query Channel
in the state, so as to achieve a thread control Selector
, and a Selector
plurality of control Channel
purposes. It is represented by this map.
Selector Use
From the chart above we can probably guess Selector
how to use
Creating Selector
By calling Selector.open()
to create a Selector method.
Selector selector = Selector.open();
复制代码
Create a Channel needed
We know that in NIO Channel is divided into four types
FileChannel
: File channelDatagramChannel
: Reading data network via UDPSocketChannel
: Reading data network by TCPServerSocketChannel
: You can listen for incoming connections, create a will for each incoming connectionSocketChannel
And in that there is not a four channels Selector
with the use, as can be seen from the figure, we Selector
are constantly registered in the polling Selector
state of each channel can not be blocked in one of the channels, each channel must i.e. is unblocked, but FileChannel
the channel is blocked and can not be changed, it FileChannel
can not be Selector
used in conjunction.
ServerSocketChannel socketChannel = ServerSocketChannel.open();
socketChannel.socket().bind(new InetSocketAddress(8080));
//设置为非阻塞模式
socketChannel.configureBlocking(false);
复制代码
Will create good Channel Selector registered with the
For ease of Selector
administration Channel
, we will Channel
register to Selector
the.
//将Channel注册到Selector上
SelectionKey selectionKey = socketChannel.register(selector,SelectionKey.OP_READ);
复制代码
We can see that the first parameter is our own Selector
, and the second parameter is to select the type of event to listen, a total of four
SelectionKey.OP_CONNECT
: Connecting to continue the event, indicates that the server listens to client connection, the server can accept the connectionSelectionKey.OP_ACCEPT
: Connecting ready event, the server receives a connection request from a client triggerSelectionKey.OP_READ
: Ready for reading event indicating the channel of the data has been read, a read operation may be performedSelectionKey.OP_WRITE
: Write-ready event, said it had to write the data to the channel
ServerSocketChannel
The events are effectiveOP_ACCEPT
,SocketChannel
effective eventsOP_CONNECT
,OP_READ
,OP_WRITE
Loop through each Channel Selector
In the last step we have required Channel
registration to Selector
, then we can now call the Selector.select()
method has been traversed to get ready Channel
.
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while(keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if(key.isAcceptable()) {
// a connection was accepted by a ServerSocketChannel.
} else if (key.isConnectable()) {
// a connection was established with a remote server.
} else if (key.isReadable()) {
// a channel is ready for reading
} else if (key.isWritable()) {
// a channel is ready for writing
}
keyIterator.remove();
}
复制代码
Note that at this time we traversed after completion, after the completion of the corresponding operation should call the
keyIterator.remove();
method to remove it out, because theselect()
method has only been all readyChannel
set of values key, if not removed, then the next traversal will still remain call the corresponding event.
Complete Example
Make a simple server monitor program. This machine monitor 8080, the print data sent from.
public class TestNIO {
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel socketChannel = ServerSocketChannel.open();
socketChannel.socket().bind(new InetSocketAddress(8080));
//设置为非阻塞模式
socketChannel.configureBlocking(false);
//将Channel注册到Selector上
socketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true){
int readyChannel = selector.select();
if (readyChannel == 0){
continue;
}
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while (keyIterator.hasNext()){
SelectionKey key = keyIterator.next();
keyIterator.remove();
if (key.isAcceptable()){
System.out.println("isAcceptable");
SocketChannel clientChannel = ((ServerSocketChannel) key.channel()).accept();
clientChannel.configureBlocking(false);
clientChannel.register(key.selector(),SelectionKey.OP_READ);
}
else if (key.isConnectable()){
System.out.println("isConnectable");
}
else if (key.isReadable()){
SocketChannel clientChannel = (SocketChannel) key.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
clientChannel.read(byteBuffer);
System.out.println(new String(byteBuffer.array()));
}else if (key.isWritable()){
System.out.println("isWritable");
}
}
}
}
}
复制代码
At this time, by the console command telnet localhost 8080
to connect to the server.