Java NIO SocketChannel.read () with multi-threaded

I am using a simple file server using Java NIO with one stream selection and multiple workflows (to do real read / write).

The main part of the code is as follows:

while (true) { int num = selector.select(); if (num > 0) { Iterator<SelectionKey> keys = selector.selectedKeys().iterator(); final SelectionKey key = keys.next(); keys.remove(); if (key.isValid()) { if (key.isAcceptable()) { accept(key); } else if (key.isReadable()) { performReadInWorkerThread (key); } else if (key.isWritable()) { performWriteInWorkerThread (key); } } } } 

As you can see from the code snippet, when the read / write channel is selected, I unload the read / write from the selection stream to the work stream.

Now the problem is that when the read channel is passed to the workflow and before it finishes / starts reading from the channel, the loop cycle is selected again, and selector.select() selects the previously selected read channel (because there is still an input buffer in a channel that is not yet completely absorbed by the previously assigned workflow), so again the channel is transferred to another workflow , as a result of which several workflows are viewed on the same channel .

I think this is a design issue. My question is, how can I provide only one thread reading a channel at a time?

+6
source share
3 answers

Why? Reading is not blocked. Do it in the current thread. So you have endless problems. You will have to unregister OP_READ before moving on to the read stream, which is simple enough, but the tricky part is that when the read stream completes the read, it will have to reregister OP_READ, which requires either (i) the wakeup () selector, because why the selected thread starts when there is nothing to do, which is wasteful, or (ii) use the queue of pending re-registrations, which delays the next reading on this channel, until after the next selector selection it wakes up, which is also a waste iterative, otherwise you need to immediately activate the selector when adding to the queue, which is also wasteful if nothing is ready. I have never seen a compelling NIO architecture that used a variety of themes to select and read.

Do not do that. If you must have multithreading, organize your channels into groups, each of which has its own selector and its own stream, and all these streams perform their own reading.

Similarly, there is no need to write in a separate thread. Just write when you have something to write.

+6
source

For NIO, just follow one principle: Read / write in the main selection stream. This principle is a reflection of the hardware nature. Don't worry that reading in the main selection line is not fast. In a modern server, the processor is always faster than the network card. Thus, without blocking reads in a single thread, it is also faster than operations with a network card. One stream is enough to read the package. We no longer need threads.

+1
source

Check out the SelectionKey.cancel() method.

-1
source

Source: https://habr.com/ru/post/919551/


All Articles