Java ExecutorService,为队列中的所有工作设置总体固定费率

Java ExecutorService, setting an overall fixed rate for all work in a queue

给定以下代码:

ScheduledExecutorService es = new ScheduledThreadPoolExecutor(100);

es.scheduleAtFixedRate(() -> {
        System.out.println("Do work with a fixed rate! ");
}, 0, 1000, TimeUnit.MILLISECONDS);


int i = 0;
while ( i < 100 ) {
        es.scheduleAtFixedRate(() -> {
                System.out.println("Do more work with a fixed rate! Doesn't really work! We will end up with 100 'workers', each running with a fixed rate! ");
        }, 0, 1000, TimeUnit.MILLISECONDS);

        i++;
}

它创建一个 SchedueledThreadPoolExecutor

在 while 循环中,我们正在模拟其他人想要向队列中添加更多工作,但这显然行不通。

我猜,需要实现某种 ThreadPoolExecutor,它使用某种队列,可能是延迟队列。

想法是创建执行器,然后它有一个固定的速率来执行任务。如果任务完成得太快,则已完成的线程需要等待才能完成更多工作。

如果一个完成得太慢,那么全局时间应该允许线程池中的其他线程完成更多工作。

http://docs.oracle.com/javase/7/docs/api/java/util/AbstractQueue.html

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/DelayQueue.html

但我希望这已经完成了,因为这应该是一个很常见的问题。

有没有人有好的解决办法?

目前还不完全清楚你想做什么,但我猜你想要一种 Pacer 或 Throttler 来确保任务以一定的速度执行(想想办公室入口处的旋转门)建筑物等,门的速度决定了单位时间内可以进(或出)建筑物的人数和每次进(或出)的时间差。

ScheduledExecutorServcice不是该问题的解决方案。相反,从研究 Leaky Bucket Algorithm 开始。

A​​ ScheduledThreadPoolExecutor 维护一个任务队列,该队列按任务的下一次计划执行排序。这些任务(您提供的 Runnable 实例)完全独立于执行它们的线程。换句话说,线程不只是获取一个任务,执行它,然后进入睡眠状态等待该任务的下一次执行。

相反,线程轮询队列、获取任务、执行它、通过将任务重新插入队列来安排下一次执行任务,然后再次轮询队列。如果队列有任务,那就太好了。如果没有,他们会等到下一个任务准备就绪(无论它当前在队列中还是稍后添加)。然后他们重新开始整个过程​​。

综上所述,具有 100 个线程的 ScheduledThreadPoolExecutor 可以轻松地以任何类型的速率处理 100 多个任务。