1

プログラミングの練習用に人生ゲームを書いています。ジェネレーターには 3 つの異なる実装があります。1 つ目: 1 つのメイン スレッド + N 個のサブ スレッド、2 つ目: SwingWorker + N 個のサブ スレッド、3 つ目: SwingWorker + ExecutorService。N は、使用可能なプロセッサーまたはユーザー定義の数です。最初の 2 つの実装は、1 つ以上のスレッドで正常に動作します。ExecutorServise を使用した実装は、1 つのスレッドで正常に実行されますが、複数のスレッドでロックされます。私はすべてを試しましたが、解決策を得ることができません。

ここで、うまく機能する実装のコード(2番目のもの):

    package example.generator;

    import javax.swing.SwingWorker;

    /**
     * AbstractGenerator implementation 2: SwingWorker + sub threads.
     * 
     * @author Dima
     */
    public final class WorldGenerator2 extends AbstractGenerator {


        /**
         * Constructor.
         * @param gamePanel The game panel
         */
        public WorldGenerator2() {
            super();
        }




        /* (non-Javadoc)
         * @see main.generator.AbstractGenerator#startGenerationProcess()
         */
        @Override
        protected void startGenerationProcess() {
            final SwingWorker<Void, Void> worker = this.createWorker();
            worker.execute();
        }




        /**
         * Creates a swing worker for the generation process.
         * @return The swing worker
         */
        private SwingWorker<Void, Void> createWorker() {
            return new SwingWorker<Void, Void>() {

                @Override
                protected Void doInBackground() throws InterruptedException {
                    WorldGenerator2.this.generationProcessing();
                    return null;
                }
            };
        }





        /* (non-Javadoc)
         * @see main.generator.AbstractGenerator#startFirstStep()
         */
        @Override
        public void startFirstStep() throws InterruptedException {
            this.getQueue().addAll(this.getLivingCells());
            for (int i = 0; i < this.getCoresToUse(); i++) {
                final Thread thread = new Thread() {
                    @Override
                    public void run() {
                        WorldGenerator2.this.fistStepProcessing();
                    }
                };
                thread.start();
                thread.join();
            }
        }




        /* (non-Javadoc)
         * @see main.generator.AbstractGenerator#startSecondStep()
         */
        @Override
        protected void startSecondStep() throws InterruptedException {
            this.getQueue().addAll(this.getCellsToCheck());
            for (int i = 0; i < this.getCoresToUse(); i++) {
                final Thread thread = new Thread() {

                    @Override
                    public void run() {
                        WorldGenerator2.this.secondStepProcessing();
                    }
                };
                thread.start();
                thread.join();
            }
        }

    }

以下は、エグゼキュータ サービスで動作しない実装のコードです。

    package example.generator;

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

    import javax.swing.SwingWorker;

    /**
     * AbstractGenerator implementation 3: SwingWorker + ExecutorService.
     * 
     * @author Dima
     */
    public final class WorldGenerator3 extends AbstractGenerator {


        private CountDownLatch  countDownLatch;
        private ExecutorService executor;


        /**
         * Constructor.
         * @param gamePanel The game panel
         */
        public WorldGenerator3() {
            super();
        }




        /* (non-Javadoc)
         * @see main.generator.AbstractGenerator#startGenerationProcess()
         */
        @Override
        protected void startGenerationProcess() {
            this.executor = Executors.newFixedThreadPool(this.getCoresToUse());
            final SwingWorker<Void, Void> worker = this.createWorker();
            worker.execute();
        }




        /**
         * Creates a swing worker for the generation process.
         * @return The swing worker
         */
        private SwingWorker<Void, Void> createWorker() {
            return new SwingWorker<Void, Void>() {

                @Override
                protected Void doInBackground() throws InterruptedException {
                    WorldGenerator3.this.generationProcessing();
                    return null;
                }
            };
        }




        /* (non-Javadoc)
         * @see main.generator.AbstractGenerator#startFirstStep()
         */
        @Override
        public void startFirstStep() throws InterruptedException {
            this.getQueue().addAll(this.getLivingCells());
            this.countDownLatch = new CountDownLatch(this.getCoresToUse());
            for (int i = 0; i < this.getCoresToUse(); i++) {    
                this.executor.execute(new Runnable() {  
                    @Override
                    public void run() {
                        WorldGenerator3.this.fistStepProcessing();
                        WorldGenerator3.this.countDownLatch.countDown();
                    }
                });
            }
            this.countDownLatch.await();

        }




        /* (non-Javadoc)
         * @see main.generator.AbstractGenerator#startSecondStep()
         */
        @Override
        protected void startSecondStep() throws InterruptedException {
            this.getQueue().addAll(this.getCellsToCheck());
            this.countDownLatch = new CountDownLatch(this.getCoresToUse());
            for (int i = 0; i < this.getCoresToUse(); i++) {
                this.executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        WorldGenerator3.this.secondStepProcessing();
                        WorldGenerator3.this.countDownLatch.countDown();
                    }
                });
            }
            this.countDownLatch.await();

        }
    }

ここで、私のアプリケーションのサンプルを小さなランチャーでダウンロードできます。コンソールに反復の結果のみを出力します:リンク


今私のコードは次のようになります:

/* (non-Javadoc)
 * @see main.generator.AbstractGenerator#startFirstStep()
 */
@Override
public void startFirstStep() throws InterruptedException {

    this.getQueue().addAll(this.getLivingCells());      

    final ArrayList<Callable<Void>> list = new ArrayList<Callable<Void>>(this.getCoresToUse());

    for (int i = 0; i < this.getCoresToUse(); i++) {

        list.add(new Callable<Void>() {

                @Override
                public Void call() throws Exception {
                    WorldGenerator3.this.fistStepProcessing();
                    return null;
                }
            }
        );          
    }

    this.executor.invokeAll(list);
}

しかし、ここでまた同じ問題が発生します。1 つのコア (スレッド) で実行しても問題はありません。コアの数を複数に設定すると、ロックされます。私の最初の質問には、(Eclipseで)実行できる例へのリンクがあります。多分私は前のコードで何かを見落としています。

4

2 に答える 2

1

エグゼキューターの施設の使い方が少し変だと思います...

つまり、アイデアは、通常、CPU がサポートするコアの数に関連するサイズのスレッドのプールを持つ Executor を持つことです。次に、何個の並列タスクをエグゼキュータに送信し、プールからいつ、どのスレッドで何を実行するかを決定させます。

CountDownLatch については...なぜExecutorService.invokeAllを使用しないのですか? このメソッドは、送信されたすべてのタスクが完了するかタイムアウトになるまでブロックされます。したがって、あなたに代わって残っている作業のカウントを行います。または、タスクの結果が利用可能になるとすぐに消費したい場合、つまりすべてのタスクが最初に完了するのを待たない場合は、「完了したタスクの結果の消費から新しい非同期タスクの生成を切り離す」CompletionService 。

何かのようなもの

    private static final int WORKER_THREAD_COUNT_DEFAULT = Runtime.getRuntime().availableProcessors() * 2;

    ExecutorService executor = Executors.newFixedThreadPool(WORKER_THREAD_COUNT);

    // your tasks may or may not return result so consuming invokeAll return value may not be necessary in your case 
    List<Future<T>> futuresResult = executor.invokeAll(tasksToRunInParallel, EXECUTE_TIMEOUT,
                TimeUnit.SECONDS);
于 2012-04-24T06:19:04.083 に答える
1

すべてのバリアントで、for ループ内にあるためjoin、並列ではなくシリアルでスレッドを実行しています。awaitつまり、開始したばかりのスレッドが完了するまで、for ループは次の反復に進むことができません。これは、任意の時点で 1 つのスレッド (メイン スレッドまたは現在のループ反復で作成された 1 つのスレッド) のみを有効にすることになります。複数のスレッドに参加したい場合は、それらへの参照を収集してから、それらすべてを開始したループの外側で、それぞれに参加する別のループに入る必要があります。

CountDownLatchバリアントでの使用に関してExecutorsは、スレッドについて言われたことがここのラッチにも当てはまります。インスタンス var を使用しないでください。すべてのラッチを収集し、別のループで待機するローカル リストを使用します。

しかし、そもそも を実際に使用するべきではありません。CountDownLatchすべての並列タスクを のリストに入れて、それCallableを呼び出す必要ExecutorService.invokeAllがあります。すべてのタスクが完了するまで、自動的にブロックされます。

于 2012-04-23T16:33:58.043 に答える