java線程池的使用

1、newCachedThreadPool()

創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程

  /**
     * 1.創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,那麼就會回收部分空閒(60秒不執行任務)的線程
     * 2.當任務數增加時,此線程池又可以智能的添加新線程來處理任務
     * 3.此線程池不會對線程池大小做限制,線程池大小完全依賴於操作系統(或者說JVM)能夠創建的最大線程大小
     */
    public static void cacheThreadPool() {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 1; i <= 10; i++) {
            final int ii = i;
            try {
                Thread.sleep(ii * 1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            cachedThreadPool.execute(() -> out.println("線程名稱:" + Thread.currentThread().getName() + ",執行" + ii));
        }

    }

運行結果:

線程名稱: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
線程名稱:pool-1-thread-1,執行10

說明:

在Executors.java中的調用

  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

在ThreadPoolExecutor.java中的調用

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
  • 底層:返回ThreadPoolExecutor實例,
  • corePoolSize爲0;
  • maximumPoolSize爲Integer.MAX_VALUE;
  • keepAliveTime爲60L;
  • unit爲TimeUnit.SECONDS;
  • workQueue爲SynchronousQueue(同步隊列)
  •  
  • 通俗:當有新任務到來,則插入到SynchronousQueue中,由於SynchronousQueue是同步隊列,因此會在池中尋找可用線程來執行,若有可以線程則執行,若沒有可用線程則創建一個線程來執行該任務;若池中線程空閒時間超過指定大小,則該線程會被銷燬。
  • 適用:執行很多短期異步的小程序或者負載較輕的服務器

2、newFixedThreadPool

創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。

/**
     * 1.創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小
     * 2.線程池的大小一旦達到最大值就會保持不變,如果某個線程因爲執行異常而結束,那麼線程池會補充一個新線程
     * 3.因爲線程池大小爲3,每個任務輸出index後sleep 2秒,所以每兩秒打印3個數字,和線程名稱
     */
    public static void fixTheadPoolTest() {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int ii = i;
            fixedThreadPool.execute(() -> {
                out.println("線程名稱:" + Thread.currentThread().getName() + ",執行" + ii);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }

執行結果:

線程名稱:pool-1-thread-1,執行0
線程名稱:pool-1-thread-2,執行1
線程名稱:pool-1-thread-3,執行2
線程名稱:pool-1-thread-2,執行3
線程名稱:pool-1-thread-1,執行4
線程名稱:pool-1-thread-3,執行5
線程名稱:pool-1-thread-3,執行6
線程名稱:pool-1-thread-2,執行7
線程名稱:pool-1-thread-1,執行8
線程名稱:pool-1-thread-1,執行9

說明:

在Executors.java中的調用:

 public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

在ThreadPoolExecutor.java中的調用

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

 

  • 底層:返回ThreadPoolExecutor實例,
  • 接收參數爲所設定線程數量nThread,
  • corePoolSize爲nThread,
  • maximumPoolSize爲nThread;
  • keepAliveTime爲0L(不限時);
  • unit爲:TimeUnit.MILLISECONDS;
  • WorkQueue爲:new LinkedBlockingQueue<Runnable>() 無界阻塞隊列
  •  
  • 通俗:創建可容納固定數量線程的池子,每隔線程的存活時間是無限的,當池子滿了就不在添加線程了;如果池中的所有線程均在繁忙狀態,對於新任務會進入阻塞隊列中(無界的阻塞隊列)
  • 適用:執行長期的任務,性能好很多

3、newSingleThreadExecutor

創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行

  /**
     * 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行
     */
    public static void singleTheadPoolTest() {
        ExecutorService pool = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++) {
            final int ii = i;
            pool.execute(() -> out.println(Thread.currentThread().getName() + "=>" + ii));
        }
    }

運行結果:

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 

說明:

在Executors.java中的調用:

public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

在ThreadPoolExecutor.java中的調用

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
  • 底層:FinalizableDelegatedExecutorService包裝的ThreadPoolExecutor實例,
  • corePoolSize爲1;
  • maximumPoolSize爲1;
  • keepAliveTime爲0L;
  • unit爲:TimeUnit.MILLISECONDS;
  • workQueue爲:new LinkedBlockingQueue<Runnable>() 無解阻塞隊列
  •  
  • 通俗:創建只有一個線程的線程池,且線程的存活時間是無限的;當該線程正繁忙時,對於新任務會進入阻塞隊列中(無界的阻塞隊列)
  • 適用:一個任務一個任務執行的場景

 

 4、newScheduledThreadPool

創建一個可定期或者延時執行任務的定長線程池,支持定時及週期性任務執行。

  /**
     * 創建一個定長線程池,支持定時及週期性任務執行。延遲執行
     */
    public static void sceduleThreadPool() {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        Runnable r1 = () -> out.println("線程名稱:" + Thread.currentThread().getName() + ",執行:3秒後執行");
        scheduledThreadPool.schedule(r1, 3, TimeUnit.SECONDS);
        Runnable r2 = () -> out.println("線程名稱:" + Thread.currentThread().getName() + ",執行:延遲2秒後每3秒執行一次");
        scheduledThreadPool.scheduleAtFixedRate(r2, 2, 3, TimeUnit.SECONDS);
        Runnable r3 = () -> out.println("線程名稱:" + Thread.currentThread().getName() + ",執行:普通任務");
        for (int i = 0; i < 5; i++) {
            scheduledThreadPool.execute(r3);
        }
    }

說明:

在Executors.java中的調用:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

在ThreadPoolExecutor.java中的調用

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }
  • 底層:創建ScheduledThreadPoolExecutor實例,
  • corePoolSize爲傳遞來的參數,
  • maximumPoolSize爲Integer.MAX_VALUE;
  • keepAliveTime爲0;
  • unit爲:TimeUnit.NANOSECONDS;
  • workQueue爲:new DelayedWorkQueue() 一個按超時時間升序排序的隊列
  •  
  • 通俗:創建一個固定大小的線程池,線程池內線程存活時間無限制,線程池可以支持定時及週期性任務執行,如果所有線程均處於繁忙狀態,對於新任務會進入DelayedWorkQueue隊列中,這是一種按照超時時間排序的隊列結構
  • 適用:週期性執行任務的場景
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章