Java ThreadPoolExecutor应遵循提交作业的顺序



我是ThreadPoolExecutor的初学者,需要您对以下场景的专家建议

在这里,我在线程执行器中提交了30个作业,这些作业应该按顺序执行。

ThreadPoolExecutor exeSer = new ThreadPoolExecutor(5, 10, 15, TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(20));
for(int i = 0; i<30; i++) {
exeSer.submit(new MyRunnableService(i));
}

当前行为

当我提交30个作业来执行时,执行器为前5个作业创建了5个线程并开始执行。接下来的20个作业进入队列,然后执行剩下的5个作业。因此,前5个(1-5)和最后5个(26-30)作业被执行,其他(6-25)作业进入队列。

预期

预期的行为是,第一个5(1-5)应该按照corePoolSize执行,接下来的5(6-10)也应该按照maxPoolSize执行。剩下的20(11-30)应该进入队列。

问题

我想按顺序执行作业,但问题是最后5(26-30)个作业首先执行。

我是否有任何方法可以按预期改变行为,或任何其他符合要求的执行人执行?

请引导。

您看到的行为是由于ThreadPoolExecutorcorePoolSize != maxPoolSize时的实现,在JDK中我有以下内容。任务1-5导致5个addWorker调用,任务6-25排队。由于在提交任务26-30时队列可能已满,这些任务最终会出现在else if中,并导致更多的addWorker调用。因此,如果任务1-5正在运行并且工作队列中充满了任务6-25,则任务26-30可能会超出预期的顺序。添加30个以上的任务将产生RejectedExecutionException

if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
...
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);

您可以使用无限制的LinkedBlockingQueue,这意味着项目1-30按预期顺序添加到执行器:

ThreadPoolExecutor exeSer = new ThreadPoolExecutor(5, 10, 0, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());

注意,如果添加大量任务,上面可能会引入其他问题,并且不能保证执行顺序为1到30,因为在任何阶段,最多可以同时运行maxPoolSize个任务,无法保证这些任务中的哪一个首先启动。

最新更新