Java:一个接一个地从线程调用方法

时间:2013-10-20 18:58:32

标签: java multithreading

我有类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

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

2 个答案:

答案 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