0

I have class Server and subclass ClientThread. ClientThread has methods receive() and broadcast(String[] msg) used to receive and send messages from/to clients connected to server.

Scheme:

public class Server extends Thread {
    private ArrayList<ClientThread> clientThreads;
    class ClientThread extends Thread {
        public void broadcast(String[] msg) {...}
        public void receive() {
            ...
            if (msg.equals("CHANGED")) {
                resumeOthers();
        }

        public void suspendOthers() {
            for (ClientThread c: clientThreads)
                 if (c!=this)
                     try {
                         c.wait();
                     } catch (InterruptedException e) {}
        }

        public void resumeOthers() {
            for (ClientThread c: clientThreads)
            if (c!=this)
                c.notify();
        }
    }

    public void run() {
        ...
        cmd = new String[1];
        cmd[0] = "PROMPTCHANGE";
        for (ClientThread currPlayer: clientThreads) {
            currPlayer.broadcast(cmd);
            currPlayer.suspendOthers();
        }
    }
}

Now, I would like to make this ClientThreads work one after another, like this:

1. ClientThread number 1 is calling method broadcast.
Now any other ClientThread existing is freezed
(they are stored in ArrayList on Server)

2. Client (another class) replies with a message that is being caught by receive()
Now this thread is freezed, and the next one starts running

Unfortunately, my approach doesn't work. Could somebody explain me in details how to achieve that?

TeoTN
  • 515
  • 1
  • 7
  • 22

2 Answers2

1

by calling Object.wait(), you are are suspending the CALLING thread, not the thread that this object happens to be.

so in effect, you are doing a loop that blocks the calling thread N times, definitely not what you intended.

in order to pause a thread, you need to have IT wait on an objet, or have it block entering a synchronized block (or use Thread.sleep(), but usually its not a good solution). in other words, the client threads need to call wait, not the calling thread.

One addition: it seems you are new to Java threading and synchronization, I strongly suggest that you read about it before attempting this.

Google around for some docs on the subject. here is something to get you started: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

Omry Yadan
  • 31,280
  • 18
  • 64
  • 87
0

It's not clear how the sequence of execution works. Anyway, as already said by previous answers, calling x.wait() on a Object makes the current thread block on object x. Moreover, in order to call wait() and notify(), you first have to synchronize on that object, AND, when you call wait(), you should do it in a loop, checking for an external condition, because spurious wakeups can happen.

So, the correct pattern should be something like:

void waitForCondition() {
  synchronized (lockObject) {
    while (!condition) {
      lockObject.wait();
    }
  }
}

void setCondition() {
  synchronized (lockObject) {
    condition = true;
    lockObject.notify(); //or .notifyAll()
  }
}

If you want to make the threads run one after another, try http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html

Giulio Franco
  • 3,170
  • 15
  • 18