1. 程式人生 > >Java默認提供的線程池

Java默認提供的線程池

hand cond executors 一個 cnblogs locking 設置 idt sin

Java的線程池都是通過ThreadPoolExecutor來構建。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        
if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException();
this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime); this.threadFactory = threadFactory; this.handler = handler; }

在Executors工廠類中,Java默認提供了四種類型的線程池。

FixedThreadPool

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

這個線程池的特點:

  • 這是一種線程數量固定的線程池,因為corePoolSize和maximunPoolSize都為用戶設定的線程數量nThreads;
  • keepAliveTime為0,意味著一旦有多余的空閑線程,就會被立即停止掉,不過因為最多只有nThreads個線程,且corePoolSize和maximunPoolSize值一致,所以這個值無法發揮作用;
  • 阻塞隊列采用了LinkedBlockingQueue,它是一個無界隊列,由於阻塞隊列是一個無界隊列,因此永遠不可能拒絕任務。

技術分享圖片

CachedThreadPool

public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
這個線程池的特點
  • 這是一個線程數量可以“無限”擴大(不能超過整型最大值)的線程池;
  • 比較適合處理執行時間比較小的任務;
  • corePoolSize為0,maximumPoolSize為無限大,意味著線程數量可以無限大;
  • keepAliveTime為60S,意味著線程空閑時間超過60S就會被殺死;
  • 采用SynchronousQueue裝等待的任務,這個阻塞隊列沒有存儲空間,這意味著只要有請求到來,就必須要找到一條工作線程處理他,如果當前沒有空閑的線程,那麽就會再創建一條新的線程。

技術分享圖片

SingleThreadExecutor

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

這個線程池的特點:

  • 只有一個線程,使用了無界隊列LinkedBlockingQueue,某種意義上等同於newFixedThreadPool(1);
  • 因為只有一個線程,所以能夠保證所有任務是FIFO地執行。

技術分享圖片

ScheduledThreadPool

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

ScheduledThreadPoolExecutor繼承自ThreadPoolExecutor。

這個線程池的特點:

它接收SchduledFutureTask類型的任務,有兩種提交任務的方式:

  • scheduledAtFixedRate
  • scheduledWithFixedDelay

從提交方式可以看出,這個線程池主要處理定時任務或延時任務。

SchduledFutureTask接收的參數:

  • time:任務開始的時間s
  • equenceNumber:任務的序號
  • period:任務執行的時間間隔

它采用DelayQueue存儲等待的任務:

  • DelayQueue內部封裝了一個PriorityQueue,它會根據time的先後時間排序,若time相同則根據sequenceNumber排序;
  • DelayQueue也是一個無界隊列;

工作線程的執行過程:

  • 工作線程會從DelayQueue取已經到期的任務去執行;
  • 執行結束後重新設置任務的到期時間,再次放回DelayQueue

技術分享圖片

#########

Java默認提供的線程池