我有N个任务,每个任务使用一个固定的线程池的大小,通常会比N.多线程架构n个重复任务
小,因为通常会有自己特定的延迟时间(N)后重复线程短缺,应优先考虑执行不同的任务,而不是重复最近完成的任务。
我正在考虑使用带有N个嵌套的ScheduledThreadPoolExecutors的外部ThreadPoolExecutor。我不确定如何以最优方式去解决这个问题,因为每个类都维护自己的内部线程池。
我有N个任务,每个任务使用一个固定的线程池的大小,通常会比N.多线程架构n个重复任务
小,因为通常会有自己特定的延迟时间(N)后重复线程短缺,应优先考虑执行不同的任务,而不是重复最近完成的任务。
我正在考虑使用带有N个嵌套的ScheduledThreadPoolExecutors的外部ThreadPoolExecutor。我不确定如何以最优方式去解决这个问题,因为每个类都维护自己的内部线程池。
除了通过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
功能时,后来添加的任务可能不经常比早先已添加的任务执行,因为系统似乎更喜欢任务在决定下一个运行时已经在执行。
相反,我上面的解决方案正确地循环这些任务,虽然在繁忙的系统中不能保证所请求的延迟是准确的。所以他们可能会稍后执行,但至少总是按照先进先出顺序执行。
你可以使用一个PriorityBlockingQueue并使用时间戳来定义优先级 - 是这样的:
class Task {
AtomicLong lastRun;
Runnable r;
void run() {
r.run();
lastRun.set(System.currentMillis);
}
}
你ScheduledExecutorService的(一个线程)可接任务Ñ添加到一个PriorityQueue每间隔(N)。
而且你可以在你的FixedThreadPool中运行一个单独的使用者队列(使用反向比较器,以便最近运行的任务的优先级较低)。
这是一个粗略,但它应该工作。
这以最简单的方式实现我想要的。另一个好处是重复的时间间隔只有在完成当前任务后才开始计数,这正是我想要的。 – Monstieur
我不完全确定,但似乎我可以简单地使用'ScheduledThreadPoolExecutor.scheduleWithFixedDelay(Runnable命令,long initialDelay,long delay,TimeUnit unit)'来一次性添加所有任务。如果'initialDelay'为'0',这是否不会自动排列任务,以保证新任务总是在重复之前运行,并且重复将按延迟到期的顺序运行? – Monstieur
如果你使用fixedDelay或fixedRate函数,这可能会起作用,但是一旦你在每次执行后都不能改变延迟(如果这甚至是需求的话),第二:如果请求太多的任务运行,它们可能会堆积最终(取决于调度程序的实现,不确定它是如何在内部完成的),因为新任务可能没有执行时间。虽然任务也会随着我的想法一定程度上增加,但所有任务至少保证以半正规方式执行。 – TwoThe