向ExecutorService对象提交任务的执行顺序是什么?

问题描述 投票:0回答:2

向ExecutorService对象提交的任务的执行顺序是什么?

场景:让我们暂时假设执行器线程池大小为5,并且我已向其提交了20个可运行任务,我们知道一次只能执行5个任务,其余任务将在存储桶中等待。所以我的问题是提交任务以什么顺序执行。它遵循FIFO数据结构还是从存储桶中随机选择任务。

此外,有什么方法可以指定执行顺序。

示例:

ExecutorService executor = Executors.newFixedThreadPool(5);
for(int i =0; i < 100; i++){
  executor.submit(() -> {
    System.out.println("print task");
  })
}
java executorservice executor
2个回答
0
投票

取决于线程池和队列的实现。

就ThreadPoolExecutor而言,队列几乎始终是SynchronousQueue,LinkedBlockingQueue或ArrayBlockingQueue。ArrayBlockingQueue和LinkedBlockingQueue保证FIFO顺序。对于SynchronousQueue,它取决于同步机制的FIFO能力,因为SynchronousQueue一次只能保留一个元素。您最好假设它不能保证。

对于ScheduledThreadPoolExecutor,该队列是DelayQueue。基本上,这是一个优先级队列,很可能使用堆数据结构实现。任务将按照延迟的顺序从队列中取出,但是对于两个具有相同延迟的任务,无法保证FIFO。

但是,毕竟,考虑到线程的前置特性,从队列中选择一个任务并不意味着将立即执行该任务。执行程序的主循环基本上看起来像这样:

public void run () {
    while(!terminated) {
        Runnable task = queue.take();
        task.run();
    }
}

考虑到两个线程正在运行此代码。这种情况可能会发生:

  1. 线程1:Runnable task = queue.take()
  2. 线程2:Runnable task = queue.take()
  3. 线程2:task.run();
  4. 线程1:task.run();

而且,第二个任务排在队列之后,但是在第一个任务之前执行。实际上,这种情况一直存在。

最后,您不能也不应承担任何责任。


0
投票

它使用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>());
    }
© www.soinside.com 2019 - 2024. All rights reserved.