線程精進指南之線程池進階

爲何引進線程池
魚池,咱們能夠釣出來一條再放回去,釣出來一條再放回去,這樣來撩魚。緩存

那線程池該如何玩呢?對,取出來一「條」線程,用完後再扔回去,再取出來,再扔....ide

線程池的優勢:性能

避免大量的建立和銷燬帶來的性能開銷線程

避免大量的線程間因互相搶佔系統資源致使的阻塞現象。設計

可以對線程進行簡單的管理並提供定時執行、間隔執行等功能。code

缺點對象

佔用必定的內存空間。接口

線程越多CPU的調度開銷越大。隊列

程序的複雜度會上升。內存

線程池的基本使用
使用線程池 ,確定要對「池」進行配置,像基本的池多大啊,能容納多少魚啊,等這些是須要建造前就要肯定的,所以咱們搞池以前先設計

• int corePoolSize 核心線程最大數

 不管是閒置仍是工做中,永遠都不會銷燬的線程,會一直在線程池中存在,那咱們是否是永遠都奈何不了它呢,固然不會,把ThreadPoolExecutor的allowCoreThreadTimeOut這個屬性設置爲true,超過規定時長也會銷燬

• int maximumPoolSize 線程總數最大值

 就是咱們全部的線程啊,對,包括非核心的和上邊講的核心的

• long keepAliveTime

 若是不是核心線程,超過這個參數的時間就會被幹掉

• TimeUnit unit

 時間老是有單位的吧,對就是上邊KeepAliveTime的時間參數哇

 類型時枚舉,這裏舉幾種經常使用的,反正說多了也記不住,須要時候IDEA會提示

 SECONDS : 秒

 MINUTES : 分

 HOURS : 小時

 DAYS : 天

• BlockingQueue workQueue  

 隊列內容較多,咱們下邊單獨講

• ThreadFactory threadFactory

 這個通常不用,不必管啦

• RejectedExecutionHandler handler

 若是執行的過程當中,拋異常了,咱們能夠用這個來指定,可是系統有默認的,所以這個也能夠不用

 

使用線程池固然離不開Executor這個接口,具體的實現類在ThreadPoolExecutor中,so咱們簡單瞭解下這個類

//對,使用的就是這幾個構造,參數咱們上邊已經將過了

public class ThreadPoolExecutor extends AbstractExecutorService {
    .....
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long  keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);
 
    public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
    ...
}

 

經常使用的幾種線程池
線程都池都是是使用Executors這個類建立出來的

• CachedThreadPool()

 可緩存線程池:

 線程數無限制

 優先使用空閒線程,若是沒有才新建線程

 //建立方式
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

//源碼中的定義

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

 

• FixedThreadPool()

 固定長度的線程池

 能夠控制線程的數量

 若是超過則必須排隊執行

 //建立方式
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(線程數量);

//源碼中的定義

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

• ScheduledThreadPool()

 對,就是它能夠定時

 //建立方法
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(最大線程數);

//源碼中的定義

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

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

• SingleThreadExecutor()

 全部任務排隊執行,一次只能執行一個任務

 //建立方法
ExecutorService singleThreadPool = Executors.newSingleThreadPool();

//源碼中的定義

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,

                                new LinkedBlockingQueue<Runnable>()));

隊列
隊列相似咱們的集合,實現了Collection接口

隊列中排隊執行的是咱們runnable對象

經常使用的隊列有以下幾種

• SynchronousQueue:

 有任務來就執行交給空閒線程,若是沒有就新建線程執行,so 線程數設置儘量大即Integer.MAX_VALUE

• LinkedBlockingQueue:

 永遠在覈心線程內使用線程,若是超過了核心的線程就在隊列中等待執行

• ArrayBlockingQueue:

 優先使用核心線程數,其次使用非核心的,若是用完了就進入隊列等待

• DelayQueue:

 想進入隊列必須實現Delayed接口,達到指定時間後,方可執行任務

 

讀書百遍不如代碼十遍,提高的惟一道路惟有你的手速!

相關文章
相關標籤/搜索