0

main(father)スレッドを作成するときに、いくつかのロジックを実装しようとしています。witchは他のいくつかのスレッドを実行します。次に、子スレッドが作成する条件を待ちます。条件が満たされた後、父親はさらにいくつかの子スレッドを実行します。wait / notifyを使用すると、java.lang.IllegalMonitorStateException例外が発生するという問題。コードは次のとおりです。

public class MyExecutor {

final static ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(10);
final static ExecutorService svc = Executors.newFixedThreadPool(1);
static final ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 8, 10, TimeUnit.SECONDS, queue);

public static void main(String[] args) throws InterruptedException {
    final MyExecutor me =  new MyExecutor();
    svc.execute(new Runnable()  {
        public void run() {
            try {
                System.out.println("Main Thread");
                me.execute(threadPool, 1);
                System.out.println("Main Thread waiting");
                wait();
                System.out.println("Main Thread notified");
                me.execute(threadPool, 2);
                Thread.sleep(100);
                threadPool.shutdown();
                threadPool.awaitTermination(20000, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });

    svc.shutdown();
    svc.awaitTermination(10000, TimeUnit.SECONDS);
    System.out.println("Main Thread finished");
}

public void execute(ThreadPoolExecutor tpe, final int id) {
    tpe.execute(new Runnable()  {
        public void run() {
            try {
                System.out.println("Child Thread " + id);
                Thread.sleep(2000);
                System.out.println("Child Thread " + id + " finished");
                notify();
            } catch (InterruptedException e) {

                e.printStackTrace();
            }
        }
    });
}

}

待機して通知行にコメントすると、次の出力が表示されます。
メイン
スレッド待機中
メインスレッド通知済み
子スレッド1
子スレッド2
子スレッド1
終了子スレッド2終了
メインスレッド終了

4

1 に答える 1

7

コードには一連の設計上の欠陥があります。


wait()両方を呼び出すとnotify()、オブジェクトのロックの所有者である場合にのみ発生する必要があります。

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

異なるオブジェクト(内部クラス!)を呼び出しています-1つのスレッドが1つのオブジェクトを待機している場合は、同じオブジェクトを呼び出す必要wait()がありますnotify()notify


これを見逃す可能性がありますnotify

me.execute(threadPool, 1);

前に呼び出されますwait-非常に深刻なバグ(競合状態の可能性)。

他の人は、いくつかのより高いレベルの同期方法を使用することを提案するかもしれませんが、基本を理解することが重要です。

于 2011-03-20T16:21:07.137 に答える