我有类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
不幸的是,我的方法不起作用。 有人可以详细解释我如何实现这个目标吗?
答案 0 :(得分:1)
通过调用Object.wait(),您将挂起CALLING线程,而不是该对象恰好是的线程。
所以实际上,你正在做一个阻塞调用线程N次的循环,绝对不是你想要的。
为了暂停一个线程,你需要IT等待一个objet,或让它阻止进入一个synchronized块(或使用Thread.sleep(),但通常它不是一个好的解决方案)。 换句话说,客户端线程需要调用wait,而不是调用线程。
一个补充: 看来你是Java线程和同步的新手,我强烈建议你在尝试之前先阅读它。
谷歌围绕这个主题的一些文档。 这是让你入门的东西: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
答案 1 :(得分:0)
目前尚不清楚执行顺序如何运作。
无论如何,正如前面的答案所说,在x.wait()
上调用Object
会在对象x上生成当前线程块。此外,为了调用wait()
和notify()
,您首先必须同步该对象,并且,当您调用wait()
时,您应该在循环中执行此操作,检查外部因为spurious wakeups可能会发生。
因此,正确的模式应该是:
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