0

私はJavaマルチスレッドに非常に慣れていません。Javaスレッドでcountdownlatchとexecutorを学習しようとして、次のコードを実装しました-

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorBasicFramework {


    class MyThread extends Thread{

        int iCount ; String name;
        CountDownLatch latch;

        public MyThread(int iCount, String name, CountDownLatch latch) {
            super();
            this.iCount = iCount;
            this.name = name;
            this.latch = latch;         
        }

        @Override
        public void run() {
            for(int i=0;i<10;i++){
                System.out.println(name+" Printing .... "+ ++iCount+" L "+latch.getCount());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }               
            }
            latch.countDown();

        }

    }

    public ExecutorBasicFramework() {
        createThread();
    }


    private void createThread() {
        ExecutorService exec = Executors.newFixedThreadPool(10);
        CountDownLatch latch = new CountDownLatch(10);
        for(int i=0;i<10;i++){          
            MyThread thread = new MyThread(i*10, ""+i,latch);
            exec.execute(thread);

            try {
                latch.await();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        exec.shutdownNow();     

    }

    public static void main(String[] args) {
        new ExecutorBasicFramework();
    }

}

来る出力は次のとおりです-

0 Printing .... 1 L 10
0 Printing .... 2 L 10
0 Printing .... 3 L 10
0 Printing .... 4 L 10
0 Printing .... 5 L 10
0 Printing .... 6 L 10
0 Printing .... 7 L 10
0 Printing .... 8 L 10
0 Printing .... 9 L 10
0 Printing .... 10 L 10

そして、流れは待ち続けるようなものです。私の予想される出力は上記のようなものですが、 0 を出力した後、 1 から 9 まで同様の出力を出力し、プログラムを停止する必要があります。

カウントダウンラッチは待っていて待っていて、エグゼキューターの次のカウンターをインクリメントしないと思います。そのため、期待される出力を取得できません。次のような出力を期待しています-

0 Printing .... 1 L 10
0 Printing .... 2 L 10
0 Printing .... 3 L 10
0 Printing .... 4 L 10
0 Printing .... 5 L 10
0 Printing .... 6 L 10
0 Printing .... 7 L 10
0 Printing .... 8 L 10
0 Printing .... 9 L 10
0 Printing .... 10 L 10


1 Printing .... 11 L 9
1 Printing .... 12 L 9
1 Printing .... 13 L 9
1 Printing .... 14 L 9
1 Printing .... 15 L 9
1 Printing .... 16 L 9
1 Printing .... 17 L 9
1 Printing .... 18 L 9
1 Printing .... 19 L 9
1 Printing .... 20 L 9

and So on ... 
2 Printing .... 21 L 8
2 Printing .... 22 L 8
2 Printing .... 23 L 8

ラッチの各デクリメント カウンターで、次のスレッドはプールで、10 までカウントを実行する必要があります。その後、再びラッチ カウンターを減少させる必要があり、スレッド 9 が同じ処理を完了するまでプロセスが繰り返されます。

入力を提案してください。

4

3 に答える 3

3

したがって、カウントダウン値を 10 に設定してnew CountDownLatch(10)いますが、コードはスレッドごとに 1 回だけ減分しています。スレッドを 1 つだけフォークした後、ラッチを待ちますが、ラッチは 9 のままです。

MyThread thread = new MyThread(i*10, ""+i,latch);
exec.execute(thread);
latch.await();

あなたが何を意図したのかわかりませんが、おそらくスレッドの for ループlatch.countDown();にあるはずですか?

for(int i=0;i<10;i++) {
   ...
   // if you want the latch to count-down 10 times, it should be inside the loop
   latch.countDown();
}
// it should not go here, outside the loop

すべてのジョブが完了するのを待つことが目標の場合は、次のExecutorService.awaitTermination(...)メソッドを使用してそれを行うことができます。

// submit jobs in loop
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);

また、クラスで拡張するべきではありません。を実装する必要があります。コードが機能する唯一の理由は、それも実装しています、. は、ではなく、または を使用します。サービスの内部でスレッドを管理します。ThreadMyThreadRunnableThreadRunnableMyThreadThreadExecutorServiceRunnableCallableThread

于 2013-02-26T17:39:13.593 に答える
1

CountDownLatchを使用して、main()すべてのスレッドが実行されるまでメソッドを待機させることが意図されている場合は、スレッドをサブミットするループのlatch.await() 外側に を移動する必要があります。InterruptedExceptionまた、中断フラグを再度設定せずに を食べてはいけません。(この記事を参照)。

修正は次のようになります。

for(int i=0;i<10;i++){          
    MyThread thread = new MyThread(i*10, ""+i,latch);
    exec.execute(thread);
}
try {
    latch.await();
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

これは確かに機能しますが、ExecutorService. を使用するのsubmit()ではなく、返された byをexecute()使用して、それを呼び出して送信の完了を待つことができます。Futuresubmit()Runnableget()

于 2013-02-26T20:17:10.030 に答える
0

ご意見ありがとうございます。私が期待したものを得るために、もう1つの簡単な解決策を見つけました。Executors.newSingleThreadExecutor();すべてのタスクが順次実装されることが保証されているため、これを使用しました。

于 2013-02-27T15:27:24.260 に答える