簡體   English   中英

提交給 ExecutorService 對象的任務的執行順序是什么?

[英]What is the order of execution for submitted task to the ExecutorService object?

向 ExecutorService 對象提交的任務的執行順序是什么?

場景:讓我們暫時假設 Executor 線程池大小為 5,我已經向它提交了 20 個可運行任務,我們知道一次只能執行 5 個任務,其余任務將在存儲桶中等待。 所以我的問題是提交的任務以什么順序執行。 它是遵循 FIFO 數據結構還是從桶中隨機選擇任務。

另外,有沒有辦法指定它應該以何種順序執行。

例子:

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

它使用 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>());
    }

這取決於線程池和隊列的實現。

在 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();

瞧,第二個任務排在隊列之后,但在第一個任務之前執行。 在實踐中,這種情況一直在發生。

最后,你不能也不應該假設任何事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM