[java] Thread + socket = locking my application

Started by
10 comments, last by Son of Cain 18 years, 8 months ago
Hi, I'm trying to do a server. I'm having trouble with the sockets:

public void run() {
   while(XThread.Delay(m_threadIntervall)) {
      System.out.println("trying to connect");

      try {
         m_acceptSelector.select();
      } catch(IOException e) {
         System.out.println(e.toString());
      }
					
   }
}
the m_acceptSelector.select(); doesn't throw any exception but the thread hangs up with that call and so does the rest of my application. and if I have:

public void run() {
   while(XThread.Delay(m_threadIntervall)) {
	System.out.println("trying to connect");				
   }
}
Then the thread works just fine, but the rest of my application stops running? I'm having something like this:

//create a JFrame...
MyJFrame() {
   thread.run();
   this.setVisible(true);
}
So when I comment away thread.run(), the application continues and the window pops up. But now the thread runs all the time and the window never pops up.

public class XThread extends Thread {
   public static boolean Delay(long millisecDelay) {
	if(interrupted()) {
		return false;
	}
	try {
		sleep(millisecDelay);
	} catch (InterruptedException e) {
		return false;
	}
		
	return true;
   }
}
Would appreciate any help on this, thx !
Advertisement
I remember that under certain circunstances, select() is a blocking call. You using NIO, right? If so, post the code where you create the ServerSocketChannel, and where you start the "multiplexing".

Son Of Cain
a.k.a javabeats at yahoo.ca
Yep i'm using nio. This is the requested code:

ServerSocketChannel channel = null;try {			    channel = ServerSocketChannel.open();    channel.socket().bind(new InetSocketAddress(nPort));    channel.configureBlocking(false);		            channel.register(m_acceptSelector, SelectionKey.OP_ACCEPT);} catch (IOException e) {	    System.out.println(e.toString());}


The multiplexing starts in the run() function, with the m_acceptSelector.select();

Then I get all the keys etc...
Thread.run() is on a loop, and it is blocking, so the setVisible(true) isn't reached. Yep, the select() method is blocking, tough I can't figure out why. There are some NIO pros on these forums, they will probably figure it out for you. Until then, you could search the Sun forums, there's a lot of useful information there as well.

Son Of Cain
a.k.a javabeats at yahoo.ca
Yeh, I figured the run() thingy out... I don't know why I used that ;/ everywhere
eles I use thread.start();

Yeh, and as for the select()... I have got no clue at all.

thx !
We had a big discussion over this earlier where we got into a discussion about select() and how it "blocks" the thread calling it. Technically I believe it's still non-blocking IO, though. How's that for confusing? It's also made worse by the fact that the API docs say select is blocking.

There's more than one way to possibly fix what you're doing there, one of which is to have the networking code that calls select() in a different thread entirely. The other easier option, which I'm not sure you'll experience problems with (although I never did), is to simply replace select() with selectNow(). As long as you don't block the thread that calls selectNow() in any way, your networking code should work fine. Look the methods up in the API docs, you'll see what I mean.

Just make sure that selectNow() gets called very often and continuously, otherwise you won't be getting anything over the network.
Quote:Original post by Son of Cain
I remember that under certain circunstances, select() is a blocking call. You using NIO, right? If so, post the code where you create the ServerSocketChannel, and where you start the "multiplexing".

Son Of Cain


I think you're referring to a situation where there's intermittent network traffic and not too much activity. Games can easily fit into this category... (although most probably don't) select() will effectively block the thread calling it if there's nothing for it to do. I wouldn't call this "blocking IO", I think they're different, but I'm not 100% familiar with what's going on behind the scenes (nor do I remember enough to comment further.)
Thx guys!

the selectNow works great :)

another sollution would be to interrupt the thread and make a new one:

m_thread.interrupt();
int i = m_net.m_acceptSelector.select();
m_thread = new XThread(this);

Though I don't know how effective that would be ;)

Anyway, the selectNow() works great

Thx!
First of all, let me say I understand how weird this stuff can seem at first. I have written a non-blocking IO client/server package that we use where I work. It is important to understand why to use these things, and what they are for. First of all, the nio networking stuff added the concept of channels. These can be configured for non-blocking, but they can block if you don't set them. Non-blocking IO in networking means that when you say channel.write(bytes) that method returns right away. The same goes for channel.read(). If you were using blocking, then calling channel.read() would just sit there until something came in over the network. In order to stop this, you put that code in it's own thread, so when it blocks, the rest of the program keeps running. If you are using non-blocking IO, then this code that is in its own thread burns through the while loop when there is no internet messages comming in. This is why you use the selector. The channel is registered with the selector, and the selector blocks. When something comes in, the selector.select() method returns, and then you can get the set of registered keys that tell you what socket has something comming or going. The main reason to use the NBIO is that you can handle multiple connections, i.e. a server, but it also works for a client. If you just put the connection.read() in its own thread, but then you want to send some data out, you can't, because the connection is busy waiting for data to come in. By using the selector, it will wait for sending or receiving.

So non-blocking IO means the methods return right away, so that code goes in its own thread. To handle many connections or reading and writting, the selector is used to block so that the new thread isn't using 100% CPU when there is no traffic. No matter what, you need antoher thread, and that thread will block.

Hope that helps :)

I think, therefore I am. I think? - "George Carlin"
My Website: Indie Game Programming

My Twitter: https://twitter.com/indieprogram

My Book: http://amzn.com/1305076532

Quote:Original post by Glass_Knife
No matter what, you need antoher thread, and that thread will block.


Well, actually...the main point of selectNow, IIRC, is for code that uses its own custom scheduler (e.g. any single-player game). This enables it to say once a frame "hmm. wonder if any net packets have come in? I've got a few ms to spare until the next frame is due, I'll do a quick selectNow".

But, in general, and *definitely* for any server, I'd always use select() and give it its own thread.

But be careful: Sun's API docs are very loose about blocking, including sentences such as (paraphrase) "this might not block. Particularly good implementations will not block for long at this point, if at all; other implementations may always block". IME so far on 3 platforms of Sun's JVM is that it always blocks indefinitely at all those points. But if you switch to IBM or similra you might potentially find it behaves differently - and that would be legal.

This topic is closed to new replies.

Advertisement