-3

スレッドを使用してJavaでステートメントを印刷しようとしています。各スレッドはステートメントの一部を印刷する必要があります。ただし、次のコードは常に正しい順序でステートメントを出力するとは限りません。

class NewThread implements Runnable {
    String msg;
    Thread t;
    NewThread(String str) {
        t = new Thread(this);
        msg = str;
    }
    public void run() {
        PrintMsg(msg);
    }
    synchronized void PrintMsg(String msg) {
        System.out.println(msg);
        try {
            wait();
        } catch (InterruptedException e) {
            System.out.println("Exception");
        }
        System.out.println(msg);
        notify();
    }
}
class ThreadDemo {
    public static void main(String args[]) {
        NewThread t1, t2, t3;
        t1 = new NewThread("Humphry Dumprey");
        t2 = new NewThread("went to the hill");
        t3 = new NewThread("to fetch a pail of water");
        t1.t.start();
        t2.t.start();
        t3.t.start();
        try {
            t1.t.join();
            t2.t.join();
            t3.t.join();
        } catch (InterruptedException e) {
            System.out.println("Main Thread Interrupted");
        }
    }
}

スレッド間通信に問題があると思われます。

4

1 に答える 1

1

あなたの問題はこの方法にあると思います:

synchronized void PrintMsg(String msg) {
    System.out.println(msg);
    try {
        wait();
    } catch (InterruptedException e) {
        System.out.println("Exception");
    }
    System.out.println(msg);
    notify();
}

それを呼び出すスレッドは呼び出しwait()を行うため、誰かが呼び出すのを無期限に待機しますnotify()。しかし、他に呼び出しがないnotify()ため、すべてそこで停止します。

また、メソッドは各スレッドであるため、独自のインスタンスsynchronizedも待機しています。NewThreadすべてのスレッドを同じオブジェクトで待機および通知するつもりだったと思いますか?

コメントから:

ステートメントの一部の書き込みが完了するまでスレッドを待ちたい。スレッド 1 は「Humphry Dumprey」を出力し、スレッド 2 は「丘に行った」を出力し、スレッド 3 は「バケツ一杯の水をフェッチするために」を出力し、これら 3 つのスレッドが順番に実行され、ステートメントが正しい順序で出力されるようにする必要があります。 .

私はこれらの種類の質問を決して理解していません。スレッドの要点は、非同期で並列に実行されることです。3 つ続けて印刷する場合は、代わりに 1 つのスレッドを使用する必要があります。

いくつかの課題でこれを行う必要がある場合は、いくつかの方法があります。

  • 各スレッドは同じ上で同期できAtomicIntegerます。スレッド #1 は、整数が 1 の場合は印刷を行い、スレッド #2 は 2 の場合、....順序をvalueフィールドとしてNewThreadコンストラクターに渡すことができます。値を出力した後、整数と notifyAll() をインクリメントします。

    static final AtomicInteger counter = new AtomicInteger(1);
    ...
    synchronized (counter) {
        // looping like this is always recommended
        while (counter.get() != value) {
           counter.wait();
        }
        System.out.println(...);
        counter.incrementAndGet();
        counter.notifyAll();
    }
    
  • 2 を使用すると、CountdownLatchスレッド #2 が呼び出さcountDown1.await();れ、スレッド #3 が を待機しcountDown2.await();ます。次に、スレッド #1 が呼び出すメッセージを出力しcountDown1.countDown()た後、スレッド #2 がメッセージを出力した後に呼び出しますcountDown2.countDown()

于 2013-06-11T18:17:31.697 に答える