向ExecutorService对象提交的任务的执行顺序是什么?
场景:让我们暂时假设执行器线程池大小为5,并且我已向其提交了20个可运行任务,我们知道一次只能执行5个任务,其余任务将在存储桶中等待。所以我的问题是提交任务以什么顺序执行。它遵循FIFO数据结构还是从存储桶中随机选择任务。
此外,有什么方法可以指定执行顺序。
示例:
ExecutorService executor = Executors.newFixedThreadPool(5);
for(int i =0; i < 100; i++){
executor.submit(() -> {
System.out.println("print task");
})
}
取决于线程池和队列的实现。
就ThreadPoolExecutor而言,队列几乎始终是SynchronousQueue,LinkedBlockingQueue或ArrayBlockingQueue。ArrayBlockingQueue和LinkedBlockingQueue保证FIFO顺序。对于SynchronousQueue,它取决于同步机制的FIFO能力,因为SynchronousQueue一次只能保留一个元素。您最好假设它不能保证。
对于ScheduledThreadPoolExecutor,该队列是DelayQueue。基本上,这是一个优先级队列,很可能使用堆数据结构实现。任务将按照延迟的顺序从队列中取出,但是对于两个具有相同延迟的任务,无法保证FIFO。
但是,毕竟,考虑到线程的前置特性,从队列中选择一个任务并不意味着将立即执行该任务。执行程序的主循环基本上看起来像这样:
public void run () {
while(!terminated) {
Runnable task = queue.take();
task.run();
}
}
考虑到两个线程正在运行此代码。这种情况可能会发生:
Runnable task = queue.take()
Runnable task = queue.take()
task.run();
task.run();
而且,第二个任务排在队列之后,但是在第一个任务之前执行。实际上,这种情况一直存在。
最后,您不能也不应承担任何责任。
它使用LinkedBlockingQueue来存储挂起的任务。因此,它遵循FIFO顺序处理未决任务。请找到Java文档以及方法签名。
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* {@code nThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}