【線程】ThreadPool 線程池 Executors 實戰 (十九)

我的原則:先會用再說,內部慢慢來。
學以致用,根據場景學源碼


一、工具類 Executors

1.1 UML 圖

在這裏插入圖片描述

1.2 四個常用方法

方法 描述
newCachedThreadPool 創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。 (線程可複用)
newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。
newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

1.3 線程池的作用

  1. 提供了一個線程隊列,隊列中保存着所有等待狀態的線程。避免了創建與銷燬額外開銷,提高了相應速度。

=== 點擊查看top目錄 ===

二、實戰

2.1 newCachedThreadPool 方法

  • java.util.concurrent.Executors#newCachedThreadPool() 方法,內部線程數量默認 Integer.MAX_VALUE ,線程池爲無限大。
  • newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。
  • 當執行第二個任務時第一個任務已經完成,會複用執行第一個任務的線程,而不用每次新建線程。
    public static void method_newCachedThreadPool() {
        // 1、創建線程池
        ExecutorService pool = Executors.newCachedThreadPool();
        // 2、分配任務
        for (int i = 0; i < 20; i++) {
            final int index = i;
            pool.execute(() -> {
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName() + "-" + index);
                    }
            );
        }
        // 3、關閉線程池
        pool.shutdown();
    }

輸出:

pool-1-thread-2-1
pool-1-thread-9-8
pool-1-thread-10-9
pool-1-thread-1-0
pool-1-thread-12-11
pool-1-thread-14-13
pool-1-thread-15-14
pool-1-thread-17-16
pool-1-thread-18-17
pool-1-thread-19-18
pool-1-thread-20-19
pool-1-thread-8-7
pool-1-thread-13-12
pool-1-thread-6-5
pool-1-thread-7-6
pool-1-thread-3-2
pool-1-thread-5-4
pool-1-thread-16-15
pool-1-thread-4-3
pool-1-thread-11-10

=== 點擊查看top目錄 ===

2.2 newFixedThreadPool 方法

  • java.util.concurrent.Executors#newFixedThreadPool(int)
  • newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
    public static void method_newFixedThreadPool() {
        // 1、創建線程池
        ExecutorService pool = Executors.newFixedThreadPool(4);

        // 2、分配任務
        for (int i = 0; i < 10; i++) {
            final int index = i;
            pool.execute(() -> {
                System.out.println(Thread.currentThread().getName() + "-" + index);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        // 3、關閉線程池
        pool.shutdown();
    }
  • 因爲線程池大小爲4,每個任務輸出index後sleep 2秒,所以每兩秒打印4個數字。
  • 輸出:
pool-1-thread-1-0
pool-1-thread-2-1
pool-1-thread-3-2
pool-1-thread-4-3
pool-1-thread-3-4
pool-1-thread-1-7
pool-1-thread-2-6
pool-1-thread-4-5

=== 點擊查看top目錄 ===

2.3 newScheduledThreadPool 方法

  • java.util.concurrent.Executors#newScheduledThreadPool(int) 規定池內線程最大數量

  • newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。

    public static void newScheduledThreadPoolSchedule() {
        // 1、創建線程池
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);

        // 2、分配任務
        // 啓動了兩個定時的任務,在JVM開啓後的1分鐘後,每隔2分鐘,開始執行一次。
        LoopCount loopCount = new LoopCount();

        for (int i = 0; i < 2; i++) {
            final int index = i;
            pool.scheduleAtFixedRate(() -> System.out.println(Thread.currentThread().getName() + "-" + index + "_count_" + loopCount.getCount().incrementAndGet()),
                    1, 2, TimeUnit.SECONDS);
        }
    }
    @Data
    static class LoopCount{
        private AtomicInteger count = new AtomicInteger(0);
    }

  • 定時及週期性任務操作 scheduleAtFixedRate
  • java.util.concurrent.ScheduledExecutorService#scheduleAtFixedRate 方法
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit)
  • 啓動了兩個定時的任務,在JVM開啓後的1分鐘後,每隔2分鐘,開始執行一次。
  • 輸出:
pool-1-thread-1-0_count_1
pool-1-thread-2-1_count_2
pool-1-thread-2-0_count_3
pool-1-thread-1-1_count_4
pool-1-thread-3-0_count_5
pool-1-thread-2-1_count_6
pool-1-thread-3-0_count_7
pool-1-thread-1-1_count_8
pool-1-thread-2-0_count_9
pool-1-thread-3-1_count_10
pool-1-thread-1-0_count_11
pool-1-thread-1-1_count_12
pool-1-thread-1-0_count_13

=== 點擊查看top目錄 ===

2.4 newSingleThreadExecutor 方法

  • java.util.concurrent.Executors#newSingleThreadExecutor()
  • 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。
    public static void method_newSingleThreadExecutor() {
        // 1、創建線程池
        ExecutorService pool = Executors.newSingleThreadExecutor();
        // 2、分配任務
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            final int index = i;
            pool.execute(() -> System.out.println(Thread.currentThread().getName() + "-" + index));
        }
        // 3、關閉線程池
        pool.shutdown();
    }

輸出:

pool-1-thread-1-0
pool-1-thread-1-1
pool-1-thread-1-2
pool-1-thread-1-3
pool-1-thread-1-4
pool-1-thread-1-5
pool-1-thread-1-6
pool-1-thread-1-7
pool-1-thread-1-8
pool-1-thread-1-9

三、番外篇

下一章節:【線程】ThreadPool 線程池底層剖析 (二十)
上一章節:【線程】Thread.UncaughtExceptionHandler 實戰與剖析 (十八)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章