NIO accept() loop, traditional thread for processing

Discussion in 'Java' started by John Hartnup, Apr 23, 2007.

  1. John  Hartnup

    John Hartnup Guest

    Hi folks,

    I need to change a server so that it listens on multiple addresses and
    ports, and behaves differently depending on which port is which. It
    seems straightforward enough using nio, but I'd be most grateful if
    someone would validate my approach.

    I have followed standard tutorials to create ServerSocketChannels, set
    them to non-blocking mode, and register them to a selector. Then I
    loop around selector.select().

    Here's the bit I want to validate:

    while(stopped = false) {
    selections = selector.select();
    if(selections > 0) {
    Set keys = selector.selectedKeys();
    Iterator i = keys.iterator();
    while(i.hasNext()) {
    SelectionKey key = (SelectionKey) i.next();
    ServerSocketChannel sch = (ServerSocketChannel) key.channel();
    SocketChannel chan = sch.accept();
    // chan.configureBlocking(true); // necessary? wise?
    SessionHandler handler = new SessionHandler(chan.socket());
    handler.start();
    i.remove();
    }
    }
    }

    SessionHandler is a subclass of java.lang.Thread and has no NIO
    related code in it. The toy server I've written in this way seems to
    work, but do I need to worry about blocking when I'm handling serious
    data? The existing code relies on blocking reads.

    Also, is it safe to add a stop() method:
    public void stop() {
    stopped = true;
    selector.wakeup();
    }

    ?
    John Hartnup, Apr 23, 2007
    #1
    1. Advertising

  2. John  Hartnup

    Esmond Pitt Guest

    John Hartnup wrote:


    > SessionHandler is a subclass of java.lang.Thread and has no NIO
    > related code in it. The toy server I've written in this way seems to
    > work, but do I need to worry about blocking when I'm handling serious
    > data? The existing code relies on blocking reads.


    Your code is OK and it will handle any number of server socket channels
    in this single thread. But there's very little other benefit from using
    NIO unless everything is non-blocking.

    > Also, is it safe to add a stop() method:
    > public void stop() {
    > stopped = true;
    > selector.wakeup();
    > }


    Yes.
    Esmond Pitt, Apr 23, 2007
    #2
    1. Advertising

  3. John  Hartnup

    Lars Enderin Guest

    John Hartnup skrev:
    > Hi folks,
    >
    > I need to change a server so that it listens on multiple addresses and
    > ports, and behaves differently depending on which port is which. It
    > seems straightforward enough using nio, but I'd be most grateful if
    > someone would validate my approach.
    >
    > I have followed standard tutorials to create ServerSocketChannels, set
    > them to non-blocking mode, and register them to a selector. Then I
    > loop around selector.select().
    >
    > Here's the bit I want to validate:
    >
    > while(stopped = false) {


    How can this loop ever be executed? (stopped = false) is always false.
    Don't you mean while (!stopped) { ?
    Lars Enderin, Apr 23, 2007
    #3
  4. John  Hartnup

    John Hartnup Guest

    On Apr 23, 5:54 pm, Lars Enderin <> wrote:
    > John Hartnup skrev:
    >
    > > Hi folks,

    >
    > > I need to change a server so that it listens on multiple addresses and
    > > ports, and behaves differently depending on which port is which. It
    > > seems straightforward enough using nio, but I'd be most grateful if
    > > someone would validate my approach.

    >
    > > I have followed standard tutorials to create ServerSocketChannels, set
    > > them to non-blocking mode, and register them to a selector. Then I
    > > loop around selector.select().

    >
    > > Here's the bit I want to validate:

    >
    > > while(stopped = false) {

    >
    > How can this loop ever be executed? (stopped = false) is always false.
    > Don't you mean while (!stopped) { ?



    Actually (stopped = false) is always true, so the loop will never
    exit.

    I meant (stopped == false), or, as you correctly point out, (!
    stopped). Thanks for catching that!
    John Hartnup, Apr 23, 2007
    #4
  5. John  Hartnup

    John Hartnup Guest

    On Apr 23, 5:18 pm, Esmond Pitt <>
    wrote:

    > Your code is OK and it will handle any number of server socket channels
    > in this single thread. But there's very little other benefit from using
    > NIO unless everything is non-blocking.


    Thanks. The one important benefit I require is the ability to
    simultaneously accept() on multiple SocketAddresses. So I'm happy :)
    John Hartnup, Apr 23, 2007
    #5
  6. John  Hartnup

    Lars Enderin Guest

    John Hartnup skrev:
    > On Apr 23, 5:54 pm, Lars Enderin <> wrote:
    >>> while(stopped = false) {

    >> How can this loop ever be executed? (stopped = false) is always false.
    >> Don't you mean while (!stopped) { ?

    >
    >
    > Actually (stopped = false) is always true, so the loop will never
    > exit.


    No, the java expression (stopped = false) has the value false. The
    compiler should warn you about that.

    > I meant (stopped == false), or, as you correctly point out, (!
    > stopped). Thanks for catching that!


    There is no need to test for boolean expression equality/unequality with
    true or false, and there is an obvious risk of using = instead of ==.
    Lars Enderin, Apr 23, 2007
    #6
  7. John  Hartnup

    John Hartnup Guest

    Boolean value x = false;

    On Apr 23, 9:00 pm, Lars Enderin <> wrote:


    > No, the java expression (stopped = false) has the value false. The
    > compiler should warn you about that.


    My! I've been programming in Java for a good year without ever
    noticing that, which at least demonstrates that I gained good habits
    in my many years of C -- habitually typing "if(null == x)" instead of
    "if(x == null)".

    Thanks for the lesson. Incidentally, Eclipse does not warn about
    this. The reason it slipped into the original post was that my test
    version simply had "while(true)". The "stopped" variable was added to
    the post to support a supplemental question. Thanks again.
    John Hartnup, Apr 23, 2007
    #7
  8. John  Hartnup

    Lars Enderin Guest

    Re: Boolean value x = false;

    John Hartnup skrev:
    > On Apr 23, 9:00 pm, Lars Enderin <> wrote:
    >
    >
    >> No, the java expression (stopped = false) has the value false. The
    >> compiler should warn you about that.

    >
    > My! I've been programming in Java for a good year without ever
    > noticing that, which at least demonstrates that I gained good habits
    > in my many years of C -- habitually typing "if(null == x)" instead of
    > "if(x == null)".
    >

    It's even simpler to avoid the error in C:
    (!x) is equivalent to (x == null), as any non-zero (non-null) value is
    "true" (and 0 is false). It's a little obscure, though:
    if (!strcmp(foo, bar)) { /* foo equals bar */ ... }
    is counter-intuitive, at least to me.
    Lars Enderin, Apr 23, 2007
    #8
  9. John  Hartnup

    Daniel Pitts Guest

    Re: Boolean value x = false;

    On Apr 23, 7:10 am, Lars Enderin <> wrote:
    > John Hartnup skrev:> On Apr 23, 9:00 pm, Lars Enderin <> wrote:
    >
    > >> No, the java expression (stopped = false) has the value false. The
    > >> compiler should warn you about that.

    >
    > > My! I've been programming in Java for a good year without ever
    > > noticing that, which at least demonstrates that I gained good habits
    > > in my many years of C -- habitually typing "if(null == x)" instead of
    > > "if(x == null)".

    >
    > It's even simpler to avoid the error in C:
    > (!x) is equivalent to (x == null), as any non-zero (non-null) value is
    > "true" (and 0 is false). It's a little obscure, though:
    > if (!strcmp(foo, bar)) { /* foo equals bar */ ... }
    > is counter-intuitive, at least to me.


    in c, strcmp(a,b) = 0 isn't valid, so you're not likely to need that
    safety on that call :)
    Part of me wishes java supported converting null/not null references
    to boolean false/true primatives.

    public void myProcess(Object a) {
    if (!a) {
    throw new NullPointerException("Cannot process nothing. Must
    process something.");
    }
    doProcess(a);
    }

    I understand the arguments against it. perhaps a special "if" syntax:
    if set(a) {
    System.out.println("A is not null");
    }
    if unset(a) {
    System.out.println("A is null");
    }

    And an associated trinary: a set? "A is not null" : "A is null";
    Daniel Pitts, Apr 23, 2007
    #9
  10. John  Hartnup

    Michael Guest

    On Apr 23, 7:39 am, John Hartnup <> wrote:
    > On Apr 23, 5:18 pm, Esmond Pitt <>
    > wrote:
    >
    > > Your code is OK and it will handle any number of server socket channels
    > > in this single thread. But there's very little other benefit from using
    > > NIO unless everything is non-blocking.

    >
    > Thanks. The one important benefit I require is the ability to
    > simultaneously accept() on multiple SocketAddresses. So I'm happy :)


    Well, technically they won't be simultaneous because they're in a
    single thread. You might do better to just have multiple server
    threads. Then if you have multiple CPUs you'll actually get better
    concurrency at the processing of multiple socket-accepts, and you'll
    have the benefit that the processing of each accept won't block the
    acceptance of the next. Having 100 such blocked threads is nothing..
    Now if you want thousands of threads, then this is probably better.
    I've seen Java stacks start to overflow at around 2,000 threads (with
    default memory settings). Incidently, a good responsive server model
    is to have a pool of worker threads able to handle all the different
    types of jobs (think web servers).. Then you can use the NIO select or
    have a different thread on each accept listener - they all just hand
    off to the worker pool. In this way a single IO-blockage won't stall
    the entire server, but at the same time, you can never overload the
    server because it won't process more than k-jobs at a time. java 5
    has some nice Executors.createXXXThreadPool(n) helpers for this.
    Michael, Apr 24, 2007
    #10
  11. John  Hartnup

    Esmond Pitt Guest

    Michael wrote:
    > Well, technically they won't be simultaneous because they're in a
    > single thread. You might do better to just have multiple server
    > threads. Then if you have multiple CPUs you'll actually get better
    > concurrency at the processing of multiple socket-accepts, and you'll
    > have the benefit that the processing of each accept won't block the
    > acceptance of the next.


    This is a bit futile really, as accepted connections are already queued
    in the kernel, and as all the accepting thread has to do is register the
    accepted channel with the selector. A well-written accept loop isn't a
    bottleneck.
    Esmond Pitt, Apr 25, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. iksrazal

    NIO with timeouts != NIO?

    iksrazal, Jun 17, 2004, in forum: Java
    Replies:
    1
    Views:
    6,231
    iksrazal
    Jun 18, 2004
  2. -
    Replies:
    1
    Views:
    335
    Esmond Pitt
    Jul 5, 2005
  3. Qu0ll
    Replies:
    10
    Views:
    1,975
    Qu0ll
    Nov 12, 2007
  4. Ralph Smith
    Replies:
    3
    Views:
    138
    Pit Capitain
    Oct 19, 2005
  5. Isaac Won
    Replies:
    9
    Views:
    354
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page