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() を使用しますが、通常は適切な解決策ではありません)。つまり、呼び出しスレッドではなく、クライアント スレッドが wait を呼び出す必要があります。

1 つ追加: Java のスレッド化と同期化は初めてのようです。これを試みる前に、それについて読むことを強くお勧めします。

この件に関するいくつかのドキュメントについては、Google で検索してください。ここから始めましょう: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

于 2013-10-20T19:25:15.357 に答える
0

実行シーケンスがどのように機能するかは明らかではありません。とにかく、以前の回答ですでに述べたようx.wait()に、 aObjectを呼び出すと、現在のスレッドがオブジェクト x でブロックされます。さらに、 and を呼び出すwait()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 に答える