1

synchronized(object) {object.wait()}' ' を使用して、オブジェクトの準備ができるまでサーバーを一時停止しようとしています。そしてsynchronized(object) {object.notify() }、オブジェクト値を設定するクラスで ' ' を呼び出しました。しかし、サーバーが の後に起動しないようwait()です。

public class MyServer {
...
do {
            try {

                message = (String) in.readObject();
                System.out.println("server receive>" + message);

                synchronized (myServerSend) {
                    myServerSend.wait();
                }

                System.out.println("Am I wake up???"); //this never print out

                sendMessage(myServerSend);

            } catch (ClassNotFoundException classnot) {
                System.err.println("Data received in unknown format");
            }
        } while (!message.equals("bye"));

    } catch (IOException ioException) {
        ioException.printStackTrace();
    }
....
}

オブジェクト値を設定するための私の呼び出しは次のとおりです

public class Action implements MouseInputListener, MouseMotionListener {

    ....

    public void mouseClicked(MouseEvent e) {


        if (SwingUtilities.isLeftMouseButton(e)) {...
    }

        else {
            ....
            if(MyGame.currentPlayer == MyGame.WHITE) {
                    myServerSend = "" + chosenPieceIndex + "," + moveLocationIndex;
                    synchronized (myServerSend) {

                        myServerSend.notify(); // this seems like fail to wake up myServer

                    }
                    System.out.println(myServerSend);
}

myServerSend を public static 文字列型として宣言すると問題になりますか? 誰でもそれを手伝ってもらえますか?前もって感謝します!

4

3 に答える 3

2

待機する前に通知コードに到達した可能性があります。その理由から(また、偽のウェイクアップのためにも、whileループ内に常にthread.wait()を配置する必要があります-しかし、この理由でdo whileで十分です)。

于 2013-02-14T20:38:55.363 に答える
0

すべてのコードを確認せずに決定的な答えを出すのは少し難しいですが、問題は次の場所にある可能性があります。

myServerSend = "" + chosenPieceIndex + "," + moveLocationIndex;
synchronized (myServerSend) {
    myServerSend.notify(); // this seems like fail to wake up myServer
}

このオブジェクト (myServerSend) が実際に MyServer.myServerSend オブジェクトと同じであると確信していますか? myServerSend は Action クラスで作成されているようで、予想される順序は MyServer、次に Action であると説明されていますが、私が言うように、myServerSend は MyServer で作成されているようです。

言い換えると、イベントの順序が MyServer で、次に Action である場合、ロック オブジェクトが両方の外部または MyServer クラスで作成されると予想していました。

推測では、あなたは同じオブジェクトで同期していないと思います。これが本当なら、あなたが見ている動作を説明するでしょう.

ただし、これが同じオブジェクトであることが確実な場合、イベントの順序はアクション、次に MyServer でなければなりません(または、MyServer で NullPointerException が発生します)。待って、コードは永遠に待機ポイントにとどまり、すでに逃したという通知を待ちます。

于 2013-02-14T21:22:14.850 に答える
0

書かれたコードの何が問題なのか正確にはわかりませんが、コードは本質的に安全ではありません。何もしなければ、 の呼び出しwait()が前に発生するという保証はありませんnotify()。notify が最初に発生した場合、待機は永久に続きます。さらに、wait は誤ってウェイクアップする可能性があるため、修正しても正しいコードは得られません。

スレッドは、通知、中断、またはタイムアウトなしでウェイクアップすることもできます。これは、いわゆるスプリアス ウェイクアップです。これは実際にはめったに発生しませんが、アプリケーションは、スレッドが起動される原因となったはずの条件をテストし、条件が満たされない場合は待機し続けることで、これを防ぐ必要があります。つまり、次のように、待機は常にループで発生する必要があります。

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait(timeout);
     ... // Perform action appropriate to condition
 }

このコードをCountDownLatchCyclicBarrier、またはSemaphoreに置き換えることを検討してください。これらのクラスはすべて非常に簡単で、エラーが発生しにくくなっています。 wait/notifyはレベルが低く、正しく使用するのがやや難しくなります。

于 2013-02-14T20:48:21.443 に答える