我有N个任务,每个任务在其自己的特定延迟间隔(N)之后使用固定的线程池大小重复,通常小于N.
由于线程通常不足,因此应优先执行不同的任务,而不是重复最近完成的任务。
我在考虑使用带有N个嵌套ScheduledThreadPoolExecutors的外部ThreadPoolExecutor。我不确定如何以最佳方式解决这个问题,因为每个类都维护着自己的内部线程池。
答案 0 :(得分:2)
除了使用由assylias回答的PriorityQueue之外,您还可以通过简单的执行ThreadPoolExecutor和另一个ScheduledExecutorService来解决这个问题,它将在给定的延迟之后插入任务。
因此,每个任务都有执行Runnable和插入Runnable,并且在成功执行后,会告诉ScheduledExecutorService在给定的延迟后运行插入Runnable,然后将任务放回ThreadPoolExecutor。
代码:
// myExecutionTask
void run() {
doSomeWork();
scheduledExecutor.schedule(myInsertionRunnable, 1000, TimeUnit.MILLISECONDS);
}
和
// myInsertionRunnable
void run () {
threadPoolExecutor.execute(myExecutionTask);
}
实际上,这将自动循环ThreadPoolExecutor中的任务,因为那些已经完成的任务将在队列的末尾。
编辑如评论中所述,在非常繁忙的系统上使用调度程序的fixedRate
或fixedDelay
功能时,稍后添加的任务可能比执行任务更少之前已添加,因为系统似乎更喜欢在决定下一个运行时已经执行的任务。
相比之下,我的解决方案正确地循环了这些任务,尽管在繁忙的系统上无法保证所请求的延迟是准确的。所以它们可能会在以后执行,但至少总是按FIFO顺序执行。
答案 1 :(得分:1)
您可以使用PriorityBlockingQueue并使用时间戳来定义优先级 - 例如:
class Task {
AtomicLong lastRun;
Runnable r;
void run() {
r.run();
lastRun.set(System.currentMillis);
}
}
然后,您的ScheduledExecutorService(一个线程)可以在每个时间间隔(N)将任务N添加到PriorityQueue。
你可以在你的FixedThreadPool中运行一个单独的消费者来自队列(使用反向比较器,以便最近运行的任务的优先级较低)。
这有点粗略,但它应该有用。