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?
        }
    }
}

侦听器实际上只是在线程完成时收到通知。

4

1 回答 1

1

首先,让你的numberOfThreads同步。Reader当两个线程同时完成时,您不希望它损坏。它是一个原始的 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())上,notify()当它numberOfThreads达到 3 并将上述代码放在wait().

哦,当wait()解除阻塞时,你应该仔细检查它numberOfThreads是否真的是 3,如果不是,循环回到wait(). 谷歌“虚假唤醒”来解释为什么需要这样做。

于 2012-10-25T10:11:17.320 回答