0

10 秒ごとに実行されるスケジュールされたタスクと、静的共通マップを実際に更新する 3 つのスレッドを含むスレッド プールがあります。スケジュールされたアクションは 10 秒ごとにこのマップを出力します。問題は、3 つのスレッドがマップで終了した後にスケジューラに印刷を停止させたいことです。しかし、ここに鍵があります。スケジューラをすぐに停止したくありません。最初に印刷 (マップの最終バージョン) してから終了したいと考えています。

public class myClass implements ThreadListener {
    public static ArrayList<Pair<String, Integer>> wordOccurenceSet = new ArrayList<Pair<String, Integer>>();
    int numberOfThreads = 0;
    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    public void getAnswer(Collection<CharacterReader> characterReaders, Outputter outputter) {




        ExecutorService executor = Executors.newFixedThreadPool(characterReaders.size());
         OutputterWriteBatch scheduledThread = new OutputterWriteBatch(outputter,wordOccurenceSet);

        scheduler.scheduleAtFixedRate(scheduledThread, 10, 10, TimeUnit.SECONDS);
        for (CharacterReader characterReader : characterReaders) {
            NotifyingRunnable runnable = new CharacterReaderTask(characterReader, wordOccurenceSet);
            runnable.addListener(this);

            executor.execute(runnable);
        }



    }


    @Override
    public void notifyRunnableComplete(Runnable runnable) {
        numberOfThreads += 1;
        if(numberOfThreads == 3 ){
         //All threads finished...  What can I do to terminate after one more run?
        }
    }
}

Listener は、実際には、スレッドが終了したときに通知を受けるだけです。

4

1 に答える 1

1

まず、numberOfThreads同期させます。Reader2 つのスレッドが同時に終了したときに破損することは望ましくありません。これはプリミティブな int であるため、破損する可能性はありませんが (私は JVM に精通していません)、スレッド セーフの一般的な規則に従う必要があります。

// 1. let finish OutputterWriteBatch if currently running
scheduler.shutdown(); 
// 2. will block and wait if OutputterWriteBatch was currently running
scheduler.awaitTermination(someReasonableTimeout);
// 3. one more shot.
scheduler.schedule(scheduledThread,0);
// You could also run it directly if your outputting logic in run()
// is published via separate method, but i don't know the API so i suppose
// only Runnable is published

もちろん、これは から直接呼び出すべきではありませんnotifyRunnableComplete。リスナー メソッドはReaderスレッドから呼び出されるため、3 つのスレッドのうち最後のスレッドがタイムリーに終了するのをブロックします。むしろ、他のスレッドがwait()オンにする通知オブジェクト (できれば を実行したものgetAnswer()) を作成し、 3 に達しnotify()たときに上記のコードを の後に配置します。numberOfThreadswait()

ああ、ブロックを解除するときは、それが本当に 3 でwait()あることを再確認する必要があります。numberOfThreadsそうでない場合は、 に戻りwait()ます。これが必要な理由を説明するには、Google の「偽のウェイクアップ」を参照してください。

于 2012-10-25T10:11:17.320 に答える