当前位置: 首页 > 知识库问答 >
问题:

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

董谦
2023-03-14

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

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

还有,有没有办法指定它应该以什么顺序执行。

例子:

ExecutorService executor = Executors.newFixedThreadPool(5);
for(int i =0; i < 100; i++){
  executor.submit(() -> {
    System.out.println("print task");
  })
}

共有2个答案

法弘壮
2023-03-14

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

在ThreadPoolExecitor的情况下,队列几乎总是SynChronousQueue、LinkedBlockingQueue或ArrayBlockingQueue。ArrayBlockingQueue和LinkedBlockingQueue保证FIFO排序。对于SynChronousQueue,它取决于同步机制的FIFO功能,因为SynChronousQueue一次只能保留一个元素。您最好假设它不能保证。

在SchduledThreadPoolExecitor的情况下,队列是DelayQueue。基本上它是一个优先级队列,很可能使用堆数据结构实现。任务将按照延迟的顺序从队列中取出,但不能保证FIFO适用于具有相同延迟的两个任务。

然而,您必须考虑到,毕竟,从队列中选择任务并不意味着它将立即执行,因为线程具有先发制人的性质。执行器的主循环基本上如下所示:

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

假设有两个线程正在运行此代码。这种情况可能发生:

  1. 线程1:<代码>可运行任务=队列。take()
  2. 线程2:<代码>可运行任务=队列。take()
  3. 线程2:<代码>任务。run()
  4. 线程1:<代码>任务。run()

瞧,第二个任务在队列中排在后面,但在第一个任务之前执行。实际上,这种情况经常发生。

最后,你不能也不应该假设任何事情。

闻人弘雅
2023-03-14

它使用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>());
    }
 类似资料:
  • 问题内容: 我有三个连接的线程,即第二个线程在第一个死后执行。 这是我的代码: 我将如何使用而不是三个线程对象来实现此功能? 问题答案: 如果您想要/需要的是一个接一个地执行一组作业,但要在与主应用程序线程不同的单个线程中执行,请使用。

  • 要并行或异步运行一些东西,我可以使用ExecutorService:

  • 我正在使用sping-boot,我有这样一个用例,我想将列表的每个元素提交给执行器服务(线程池大小=4)。但是在每个必须处理的元素之间,我想要1秒钟的延迟。 Thread.sleep(1000)不工作,因为执行程序一睡觉就启动另一个线程。 编辑:这是我的process()方法,我在最后尝试使用sleep,但没有成功。

  • 我将可调用任务(使用submit())提交给ExecutionService的实现。有时我似乎遇到了死锁,但无法工作在哪里或为什么会发生,所以我想为任务设置一个超时,我不清楚是如何做到的? 我应该吗 在提交任务时,在ExecutionService上使用invokeAny()而不是submit()并设置超时。我使用submit()一次提交许多任务,我是否也可以这样使用invokeAny(),我很谨

  • 问题内容: 我已经搜索了很多,但是找不到任何解决方案。我以这种方式使用Java线程池: 以这种方式,任务以随后的顺序执行(如在队列中)。但是我需要更改“选择下一个任务”策略。所以我想为每个任务分配优先级(不是线程优先级),并执行与这些优先级相对应的任务。因此,当执行者完成另一个任务时,它将选择下一个任务作为具有最高优先级的任务。它描述了常见问题。也许有一种更简单的方法没有说明优先级。它选择上一个添

  • 我正在ThreadPoolExecutor中运行多个任务。我将其初始化如下: 我自己实现了runnable(),其中包含一个方法来跟踪提交任务的进度。我提交的实例如下: 我正在寻找一种查询当前/挂起线程的执行器/阻塞队列的方法。我尝试使用jobQueue。toArray()和重写executor方法但在这两种情况下,返回的Runnable都是FutureTask类型,不包含太多数据。有没有一种方法