我们有一个每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?
}
}
}
监听器实际上只是在线程完成时得到通知。
答案 0 :(得分: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()
达到3时将一个其他线程getAnswer()
打开的通知对象(最好是执行notify()
的那个),numberOfThreads
,并将上面的代码放在wait()
。
哦,当wait()
取消阻止时,你应该仔细检查numberOfThreads
是否真的是3,如果没有,请循环回wait()
。谷歌&#34;虚假的唤醒&#34;解释为什么需要这样做。