如何在ThreadPoolExecutor中保证FIFO执行顺序

10

我使用以下代码创建了一个ThreadPoolExecutor:

private ExecutorService executor = new ThreadPoolExecutor(5, 10, 120, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(20, true));

然后,我运行了25个任务(T01到T25),情况如下:
  • 5个任务正在运行中(T01到T05)
  • 20个任务在队列中等待(T06到T25)
当我再加入1个任务(T26)时,由于队列已满,我期望较旧的任务(T06)被删除以启动新任务(因为尚未达到MaxPoolSize限制),并且新任务(T26)被放置在队列的末尾。
但是,在现实生活中,如果队列已满且尚未达到MaxPoolSize限制,则会启动最新的任务。
所以,我有...
  • 6个任务正在运行中(T01到T05和T26)
  • 20个任务在队列中等待(T06到T25)
...而不是...
  • 6个任务正在运行中(T01到T06)
  • 20个任务在队列中等待(T07到T26)
我可以配置ThreadPoolExecutor以获得预期结果吗? 我应该使用其他类吗?
顺便提一下,这是ThreadPoolExecutor源代码的一部分。
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
        if (runState == RUNNING && workQueue.offer(command)) {
            if (runState != RUNNING || poolSize == 0)
                ensureQueuedTaskHandled(command);
        }
        else if (!addIfUnderMaximumPoolSize(command))
            reject(command); // is shutdown or saturated
    }
}


private boolean addIfUnderMaximumPoolSize(Runnable firstTask) {
    Thread t = null;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (poolSize < maximumPoolSize && runState == RUNNING)
            t = addThread(firstTask);
    } finally {
        mainLock.unlock();
    }
    if (t == null)
        return false;
    t.start();
    return true;
}

谢谢

1个回答

7

我建议将核心大小设置为最大值。这是大多数池子的使用方式,我不确定在您的情况下是否存在缺陷,但是这样可以按顺序执行任务。


我必须在这里表示同意。最坏的情况是你有5个空闲线程,它们已经被挂起了,因此不会发生任何上下文切换。 - John Vint
好的,但这有点令人沮丧-:P ThreadPoolExecutor正是我需要的,除了不能保证FIFO顺序。我的想法是尽可能保持5个线程,并在需要时暂时超载线程执行程序。如果我将maxPoolSize设置为corePoolSize,我就失去了暂时超载线程执行程序的可能性。无论如何,感谢您的回复 :-) - Jean-Marc Desprez
我有一个问题,由于队列是FIFO,如果我有10个任务(小于最小/最大核心大小),线程池能保证它们按顺序执行吗?我的意思是,如果我在run()的第一行有一些事情要做,比如printRunInfo()。那么printRunInfo()是否一定是按照FIFO的顺序执行的? - JaskeyLam
@Jaskey 如果你只有一个线程,那么它们将按顺序执行。如果你有多个线程,它们将按顺序被选中,但是当它们完成时,即使时间开始时它们可能会失去顺序。 - Peter Lawrey
@PeterLawrey,我发现了这个问题,非常遗憾,您能否回答我的问题,澄清原因并提出解决方案:http://stackoverflow.com/questions/42153013/why-tasks-in-threadpool-are-not-executed-following-fifo-java?谢谢! - JaskeyLam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接