0

我有N个任务,每个任务使用一个固定的线程池的大小,通常会比N.多线程架构n个重复任务

小,因为通常会有自己特定的延迟时间(N)后重复线程短缺,应优先考虑执行不同的任务,而不是重复最近完成的任务。

我正在考虑使用带有N个嵌套的ScheduledThreadPoolExecutors的外部ThreadPoolExecutor。我不确定如何以最优方式去解决这个问题,因为每个类都维护自己的内部线程池。

回答

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的任务,因为这已经完成了这些任务,将在队列的末尾。

编辑:正如在评论中讨论,用一个非常繁忙的系统上调度的fixedRatefixedDelay功能时,后来添加的任务可能不经常比早先已添加的任务执行,因为系统似乎更喜欢任务在决定下一个运行时已经在执行。

相反,我上面的解决方案正确地循环这些任务,虽然在繁忙的系统中不能保证所请求的延迟是准确的。所以他们可能会稍后执行,但至少总是按照先进先出顺序执行。

+1

这以最简单的方式实现我想要的。另一个好处是重复的时间间隔只有在完成当前任务后才开始计数,这正是我想要的。 – Monstieur

+0

我不完全确定,但似乎我可以简单地使用'ScheduledThreadPoolExecutor.scheduleWithFixedDelay(Runnable命令,long initialDelay,long delay,TimeUnit unit)'来一次性添加所有任务。如果'initialDelay'为'0',这是否不会自动排列任务,以保证新任务总是在重复之前运行,并且重复将按延迟到期的顺序运行? – Monstieur

+0

如果你使用fixedDelay或fixedRate函数,这可能会起作用,但是一旦你在每次执行后都不能改变延迟(如果这甚至是需求的话),第二:如果请求太多的任务运行,它们可能会堆积最终(取决于调度程序的实现,不确定它是如何在内部完成的),因为新任务可能没有执行时间。虽然任务也会随着我的想法一定程度上增加,但所有任务至少保证以半正规方式执行。 – TwoThe

1

你可以使用一个PriorityBlockingQueue并使用时间戳来定义优先级 - 是这样的:

class Task { 
    AtomicLong lastRun; 
    Runnable r; 

    void run() { 
     r.run(); 
     lastRun.set(System.currentMillis); 
    } 
} 

你ScheduledExecutorService的(一个线程)可接任务Ñ添加到一个PriorityQueue每间隔(N)。

而且你可以在你的FixedThreadPool中运行一个单独的使用者队列(使用反向比较器,以便最近运行的任务的优先级较低)。

这是一个粗略,但它应该工作。

+0

在ScheduledThreadPoolExecutor块中排队执行任务中的延迟吗?在线程池大小为1的情况下,如果我首先添加一个延迟为10秒的任务,然后添加一个延迟2秒的任务,那么第二个任务是否会先执行? – Monstieur

+0

@Locutus在我的建议中,由STPE运行的任务是向队列中添加一个任务,而不是运行它 - 因此它几乎是瞬间返回。任务由FixedThreadPoolExecutor运行,当线程变为可用时,将从PriorityQueue接收下一个任务。 – assylias

+0

我问我是在考虑一个变体,而不是你的实现。 – Monstieur