Guoxing Li
Guoxing Li

Reputation: 189

Chat system in Java

Is there a way to immediately print the message received from the client without using an infinite loop to check whether the input stream is empty or not? Because I found that using infinite loop consumes a lot of system resources, which makes the program running so slow. And we also have to do the same (infinite loop) on the client side to print the message on the screen in real time. I'm using Java.

Upvotes: 1

Views: 257

Answers (6)

Stephen C
Stephen C

Reputation: 718678

There are two approaches that avoid busy loops / sleeps.

  • Use a thread for each client connection, and simply have each thread call read. This blocks the thread until the client sends some data, but that's no problem because it doesn't block the threads handling other clients.

  • Use Java NIO channel selectors. These allow a thread to wait until one of set of channels (in this case sockets) has data to be read. There is a section of the Oracle Java Tutorials on this.

Of these two approaches, the second one is most efficient in terms of overall resource usage. (The thread-per-client approach uses a lot of memory on thread stacks, and CPU on thread switching overheads.)


Busy loops that repeatedly call (say) InputStream.available() to see if there is any input are horribly inefficient. You can make them less inefficient by slowing down the polling with Thread.sleep(...) calls, but this has the side effect of making the service less responsive. For instance, if you add a 1 second sleep between each set of polls, the effect that each client will see is that the server typically delays 1 second before processing each request. Assuming that those requests are keystrokes and the responses echo them, the net result is a horribly laggy service.

Upvotes: 0

theck01
theck01

Reputation: 203

A method that does not require threads would involve subclassing the input stream and adding a notify type method. When called this method would alert any interested objects (i.e. objects that would have to change state due to the additions to the stream) that changes have been made. These interested objects could then respond in anyway that is desired.

Objects writing to the buffer would do their normal writing, and afterward would call the notify() method on the input stream, informing all interested objects of the change.

Edit: This might require subclassing more than a couple of classes and so could involve a lot of code changes. Without knowing more about your design you would have to decide if the implementation is worth the effort.

Upvotes: 0

Jon Egeland
Jon Egeland

Reputation: 12613

If you're using Sockets, which you should be for any networking.

Then you can use the socket's DataInputStream which you can get using socket.getInputStream() (i think that's the right method) and do the following:

public DataInputStream streamIn;
public Socket soc;

// initialize socket, etc...
    streamIn = soc.getInputStream();

public String getInput() {
    return (String) streamIn.readUTF(); // Do some other casting if this doesn't work
}

streamIn.readUTF() blocks until data is available, meaning you don't have to loop, and threading will let you do other processing while you wait for data.

Look here for more information on DataInputStream and what you can do with it: http://docs.oracle.com/javase/6/docs/api/java/io/DataInputStream.html

Upvotes: 0

codemaniac
codemaniac

Reputation: 891

You don't you change your architecture a little bit to accommodate WebSockets. check out Socket.IO . It is a cross browser WebSockets enabler.

You will have to write controllers (servlets for example in java) that push data to the client. This does not follow the request-response architecture.

You can also architect it so that a "push servlet" triggers a "request" from the client to obtain the "response".

Since your question talks about Java, and if you are interested in WebSockets, check this link out.

Upvotes: 0

millhouse
millhouse

Reputation: 10007

You should be dealing with the input stream in a separate Thread - and let it block waiting for input. It will not use any resources while it blocks. If you're seeing excessive resource usage while doing this sort of thing, you're doing it wrong.

Upvotes: 2

Tikhon Jelvis
Tikhon Jelvis

Reputation: 68152

I think you can just put your loop in a different thread and have it sleep a bit (maybe for half a second?) between iterations. It would still be an infinite loop, but it would not consume nearly as many resources.

Upvotes: 0

Related Questions