Java Forum / General / April 2007
NIO accept() loop, traditional thread for processing
John Hartnup - 23 Apr 2007 08:29 GMT 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(); }
?
Esmond Pitt - 23 Apr 2007 09:18 GMT 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.
John Hartnup - 23 Apr 2007 12:39 GMT On Apr 23, 5:18 pm, Esmond Pitt <esmond.p...@nospam.bigpond.com> 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 :)
Michael - 24 Apr 2007 13:49 GMT > On Apr 23, 5:18 pm, Esmond Pitt <esmond.p...@nospam.bigpond.com> > wrote: [quoted text clipped - 5 lines] > 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.
Esmond Pitt - 25 Apr 2007 07:56 GMT > 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.
Lars Enderin - 23 Apr 2007 09:54 GMT John Hartnup skrev:
> Hi folks, > [quoted text clipped - 10 lines] > > while(stopped = false) { How can this loop ever be executed? (stopped = false) is always false. Don't you mean while (!stopped) { ?
John Hartnup - 23 Apr 2007 12:37 GMT > John Hartnup skrev: > [quoted text clipped - 15 lines] > 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!
Lars Enderin - 23 Apr 2007 13:00 GMT John Hartnup skrev:
>>> 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 ==.
John Hartnup - 23 Apr 2007 13:41 GMT > 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.
Lars Enderin - 23 Apr 2007 15:10 GMT John Hartnup skrev:
>> No, the java expression (stopped = false) has the value false. The >> compiler should warn you about that. [quoted text clipped - 3 lines] > 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.
Daniel Pitts - 23 Apr 2007 21:23 GMT > John Hartnup skrev:> On Apr 23, 9:00 pm, Lars Enderin <lars.ende...@gmail.com> wrote: > [quoted text clipped - 11 lines] > 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";
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|