Search code examples
javaselectornio

Java NIO - using Selectors


Got some quick questions on using a non blocking selector - answering any of the below would be greatly appreciated:

I have just ben learning about the selector (java NIO model) and want to clarify some facts. Picked up most of the key points from tutorials as well as the SO question: Java NIO: Selectors

so:

  1. from the question linked above, a Server socket channel is registered to listen for accept, when accepted a channel is registered for read and once read it is registered for write. How does it then go back into listening for an accept? I mean there appears to be no repeated call to a register accept listener. Is it just that once a ServerSocketChannel is registered the selector will always be listening for an accept? If so doesn't this mean that the selector will always be listening for a read/write on the channels also? How do you stop that - is it as simple as closing the channels?

  2. What happens if a channel is registered twice? I mean - in the above example, a socket is registered for write every time after a message is read - basically looks like an echo server. I guess the example assumes that the connection will then be closed after writing. What happens if you want to maintain an open connection and at different intervals write to the socket - must you register an interestOp each time? Is it harmful to register the same channel twice?

  3. Multithreading: What is the best design now for writing a multithreaded server - as the above non blocking approach assumes that one thread can handle writing and reading. Should you create a new thread if the read/write operation is expected to take a while? Are there any other points to consider?

Understand that multithreaded is for blocking IO but have seen some frameworks that use a thread pool along with a Non blocking model and was wondering why.


Solution

  • a Server socket channel is registered to listen for accept, when accepted a channel is registered for read and once read it is registered for write. How does it then go back into listening for an accept?

    It doesn't have to 'go back'. It's listening. It's registered. Nothing has changed.

    What happens if a channel is registered twice?

    The interestOps are updated and the previous key attachment is lost.

    I mean - in the above example, a socket is registered for write every time after a message is read.

    It's a very poor example. Incorrect technique. You should just write. If write() returns zero, then you should (a) register the channel for OP_WRITE; (b) retry the write when the channel becomes writable; and (c) deregister the channel for OP_WRITE once the write has completed.

    I guess this assumes that the connection will then be closed after writing.

    I don't see why. It doesn't follow. In any case it's a poor example, not to be imitated. You would be better off imitating answers here, rather than unanswered questions.

    What happens if you want to maintain an open connection and at different intervals write to the socket - must you register an interestOp each time? Is it harmful to register the same channel twice?

    See above. Keep the channel open. Its interestOps won't change unless you change them; and you should handle writing as above, not as per the poor example you cited.

    Multithreading: What is the best design now for writing a multithreaded server - as the above non blocking approach assumes that one thread can handle writing and reading.

    If you want multi-threading, use blocking I/O, most simply via java.net. If you want non-blocking I/O you don't need multi-threading. I don't understand why you're asking about both in the same question.

    Should you create a new thread if the read/write operation is expected to take a while?

    In the most general case of blocking I/O you have two threads per connection: one for reading and one for writing.