0

スレッドt1とスレッドt2に同時に通知するにはどうすればよいですか(最初に取得hey 1する確率は同じです)。hey2notifyAllを試しましたが、機能させることができませんでした。

class Thr extends Thread
{
    Thr () throws InterruptedException
    {
        Thread t1 = new Thread() {
            public synchronized void run()
            {
                while (true)
                {
                    try {
                        wait();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try
                    {
                        Thread.sleep(1500);
                    } catch (Exception e) { }
                    System.out.println("hey 1");
                }
            }
        };

        Thread t2 = new Thread() {
            public synchronized void run()
            {
                while (true)
                {                    
                    try {
                        wait();
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    try
                    {
                        Thread.sleep(1500);
                    } catch (Exception e) { }
                    System.out.println("hey 2");
                }
            }
        };

        t1.start();
        t2.start();
    }

    public static void main(String args[]) throws InterruptedException
    {
        new Thr();
    }
}
4

4 に答える 4

2

共有オブジェクトを待ち、次のようにnotifyAllを使用する必要があります。

class Thr extends Thread
{
    Thr () throws InterruptedException
    {
        final Object lock = new Object ();

        Thread t1 = new Thread() {
            public void run()
            {
                    try {
                        synchronized (lock) {
                            lock.wait();
                        }
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    System.out.println("hey 1");
            }
        };

        Thread t2 = new Thread() {
            public synchronized void run()
            {
                    try {
                        synchronized (lock) {
                            lock.wait();
                        }
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }

                    System.out.println("hey 2");
            }
        };

        t1.start();
        t2.start();
        synchronized (lock) {
            lock.notifyAll ();
        }
    }

    public static void main(String args[]) throws InterruptedException
    {
        new Thr();
    }
}
于 2012-11-11T00:28:53.780 に答える
1

これを行う正しい方法は、を使用することnotifyAllです。コードの本当の問題は、異なるミューテックスで通知を待機している2つのスレッドがあることです。@ShyJの回答で説明されているように、単一のオブジェクトを待機する必要があります。


通知が同じ確率でどちらかのスレッドに最初に配信されることが保証されるように、これをコーディングできる方法はないことに注意してください。

  • Javaスレッド仕様は、待機/通知の公平性を保証するものではありません。

  • OSレベルで(通常)実装されたスレッドスケジューラも(通常)そのような保証をしません。

重要なのは、アプリケーションがこれを制御できないということです。最善のアプローチは、wait / notifyAllに通常どおりの処理を行わせ、スレッドスケジューリングの偏りがアプリケーションの動作に重要な影響を与えないようにアプリケーションを設計することです。

(FWIW、通常の問題は、人々が明示的または暗黙的に非ランダム性を想定し、スレッドが予期しないランダムな順序でスケジュールされると燃やされることです。)

于 2012-11-11T00:33:32.030 に答える
0

待機/通知の使用を避け、より堅牢なものを使用することを強くお勧めします。問題は、待機/通知を任意の組み合わせで使用すると、競合状態が発生する可能性があることです。

それらに学術的に等しい確率を与える唯一の方法は、2つのオブジェクトを作成しSemaphore、スレッドにそれらを取得させ、Randomどちらを最初にリリースするかを選択することです。Sempahoreそれでも、スケジューラーがロックを取得しようとした最初のスケジューラーを実行することを決定した場合、それが公平であるかどうかに関係なく、とにかくそこにバイアスがかかります。これにより、viaなどで2番目のスレッドを実行する前に、最初のスレッドが完了するまで待機する必要がありますThread.join

結論として、並行システムで順序を保証する唯一の方法は、それらをシングルスレッド形式に強制することです。これにより、そもそも並行システムにするという全体的なポイントが失われます。

于 2012-11-11T00:41:57.323 に答える
0

1.4より後のバージョンのJavaを使用している場合は、次のいずれかのconcurrentロックを使用することで、タスクが大幅に簡素化されます。

java.util.concurrent.locks特にReadWriteタイプ。

今のところ、同じタイプのすべてのスレッドにメッセージを渡すために-実装Observer Pattern

于 2012-11-11T05:40:14.703 に答える