0

我有类 Server 和子类 ClientThread。ClientThread 有方法 receive() 和 broadcast(String[] msg) 用于从/向连接到服务器的客户端接收和发送消息。

方案:

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();
        }
    }
}

现在,我想让这个 ClientThreads 一个接一个地工作,像这样:

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

不幸的是,我的方法不起作用。有人可以详细解释我如何实现这一目标吗?

4

2 回答 2

1

通过调用 Object.wait(),您正在暂停 CALLING 线程,而不是该对象恰好是的线程。

所以实际上,您正在执行一个阻塞调用线程 N 次的循环,这绝对不是您想要的。

为了暂停线程,您需要让 IT 等待一个对象,或者让它阻止进入同步块(或使用 Thread.sleep(),但通常它不是一个好的解决方案)。换句话说,客户端线程需要调用等待,而不是调用线程。

一个补充:您似乎是 Java 线程和同步的新手,我强烈建议您在尝试之前阅读它。

谷歌搜索有关该主题的一些文档。这里有一些东西可以让你开始: http ://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

于 2013-10-20T19:25:15.357 回答
0

目前尚不清楚执行顺序是如何工作的。无论如何,正如之前的答案已经说过的那样,调用x.wait()aObject会使当前线程阻塞在对象 x 上。此外,为了调用wait()and notify(),您首先必须在该对象上进行同步,并且,当您调用 时wait(),您应该在循环中执行它,检查外部条件,因为可能会发生虚假唤醒

所以,正确的模式应该是这样的:

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

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

如果您想让线程一个接一个地运行,请尝试http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html

于 2013-10-20T19:34:36.013 回答