Threads which are not concurrent

Hi,

I'm having this problem in my simple server. It's purpose is just a relay chat server, but it doesn't work like expected.

I want to have several threads which take turns writing on the console or the socket. But what I get here is quite strange to me :

Сървърът слуша на порт 8503 (The server is listening to port 8503)

thread one

again thread one

/disconnect

Връзката прекъсна по желание на клиента (Connection reset by peer)

thread two

again tread two

/disconnect

Връзката прекъсна по желание на клиента (Connection reset by peer)

And here's my code :

publicclass ServerThread

extends Thread

{

private Socket socket =null;

public ServerThread(Socket sock)

{

super("Server socket thread");

socket = sock;

}

publicvoid run()

{

BufferedReader br =null;

PrintWriter pw =null;

String packet=null;

try

{

br =

new BufferedReader(new InputStreamReader(socket.getInputStream()));

pw =

new PrintWriter (socket.getOutputStream(),true);

while ((packet = br.readLine()) !=null)

{

try

{

sleep(1000);

}

catch (InterruptedException e)

{

// TODO

}

pw.println(packet);

System.out.println(packet);

if (packet.equals("/disconnect"))

{

System.out.println("Връзката прекъсна по желание на клиента");

break;

}

}

br.close();

socket.close();

}

catch (IOException e)

{

System.out.println("Грешка при създаването на нишка СървърСокет");

}

}

}

What I think would be a correct behavior :

thread one

thread two

again thread one

again thread two

[4183 byte] By [Tindora] at [2007-11-27 3:51:04]
# 1

I assume (hate that word) you have two ServerThread threads. Both with the same name and using the same socket.

Try using packet.compareTo() instead of equals().

There is no guarantee of what thread will run at any given time. Therefore, you cannot predict what the output will be.

If you want something predictable, then you need to control what thread runs when. You can do that with wait()/notify() and better await()/signal() (see the api in the java.util concurrent package.)

cooper6a at 2007-7-12 8:55:01 > top of Java-index,Core,Core APIs...
# 2

First of all, thanks for the fast answer! :)

Yes, in the test case I had two ServerThread threads, but they use different sockets, returned from the ServerSocket accept() method.

Here's how I create the threads :

public class Server

{

public static void main(String[] args)

{

ServerSocket socket = null;

if (args.length > 0)

try

{

socket = new ServerSocket(Integer.parseInt(args[0]));

System.out.println("Сървърът слуша на порт" + args[0]);

}

catch (IOException e)

{

System.out.println("Този порт вече се използва. Опитайте да зададете друг");

}

else

try

{

socket = new ServerSocket(8503);

System.out.println("Сървърът слуша на порт 8503");

}

catch (IOException e)

{

System.out.println("Този порт вече се използва. Задайте друг чрез аргументи");

}

while (true)

{

try

{

new ServerThread(socket.accept()).run();

}

catch (IOException e)

{

System.out.println("Не можах да установя връзка");

}

}

}

}

I think everything is OK with this class (at least it looks like that to me :) ). But the ServerThread class does not behave properly. I tried adding yield() and ran several tests. Always thread one gets the output first, no matter how much time it sleeps, or the yield() method it invokes.

This looks quite strange to me :(.

Tindora at 2007-7-12 8:55:01 > top of Java-index,Core,Core APIs...
# 3
First of all, read my last post about threading. Your ServerThread class in not "OK."It looks like you are starting many threads in the while(true). This will go on until you run out of memory.
cooper6a at 2007-7-12 8:55:01 > top of Java-index,Core,Core APIs...
# 4

Well, I read your previous post and googled the methods. I found the yield() method, which is supposed to give the control to some other thread, but it still does not work.

As for the while(true) loop - it's made that way in the official Sun tutorial :

http://java.sun.com/docs/books/tutorial/networking/sockets/examples/KKMultiServer.java

Tindora at 2007-7-12 8:55:02 > top of Java-index,Core,Core APIs...
# 5
> What I think would be a correct behavior :> thread one> thread two> again thread one> again thread twoWhere does that text come from, and why do you think that would be the correct behaviour?Also why the sleep()?
ejpa at 2007-7-12 8:55:02 > top of Java-index,Core,Core APIs...
# 6

Well, I've written only part of the server and I'm testing it using telnet.

I opened 2 connections and entered "thread one" on the first connection and "thread two" on the second. I did the same thing with the 2 other lines.

I think the correct behavour would be

thread one

thread two

again thread one

again thread two

because each thread will have to execute at least once, then step back and give the control to the other thread.

The sleep() is because in the Bulgarian version of Thinking in Java it was written that each thread should have sleep() in its body, in order not to take the whole cpu time and let other threads execute.

BTW I've tested it today at least 20-30 times and it's always like that - thread one executes. And when it dies, thread two steps in front.

Tindora at 2007-7-12 8:55:02 > top of Java-index,Core,Core APIs...
# 7

That's bizarre. Something lost in translation?

Threads only need to sleep when they don't perform blocking operations, and there aren't many threads that don't do that. In any case here we have readLine() which is a blocking operation.

I think the sleep is messing things up actually. Take it out, and leave it out.

ejpa at 2007-7-12 8:55:02 > top of Java-index,Core,Core APIs...
# 8

It might be a translation problem, as I found several other inaccuracies.

Well, I removed the sleep and ran the test again, this time with three threads. Here are the results:

Сървърът слуша на порт 8503 (The server is listening at 8503)

thread 1

thread 1. second line

/disconnect

Връзката прекъсна по желание на клиента (Connection reset by peer)

thread 2

thread 2. second line

/disconnect

Връзката прекъсна по желание на клиента (Connection reset by peer)

thread 3

thread 3. second line

/disconnect

Връзката прекъсна по желание на клиента (Connection reset by peer)

It seems that all threads depend on the previous one. And they don't get executed if it's still alive.

Tindora at 2007-7-12 8:55:02 > top of Java-index,Core,Core APIs...
# 9
Found it.> new ServerThread(socket.accept()).run();new ServerThread(socket.accept()).start();
ejpa at 2007-7-12 8:55:02 > top of Java-index,Core,Core APIs...
# 10
It works now. Thank you very much ! :)
Tindora at 2007-7-12 8:55:02 > top of Java-index,Core,Core APIs...