線程池詳解

一、線程池的優點緩存

(1)下降資源消耗,經過重複利用已建立的線程池減小線程建立和銷燬帶來的消耗
(2)提升效應速度,當任務來臨時,不用等待線程的建立就能當即執行
(3)提升線程的可管理性,線程是稀缺資源,若是無限制的建立,不只會消耗系統資源,還會下降系統的穩定性,線程池能夠進行管理,統一分配和監控
總的來講線程池的主要特色就是:線程複用、控制最大併發數、管理線程

二、建立線程的三個c經常使用方法併發

(1)建立有固定線程數的方法,corePoolSize等於maximumPoolSize
ExecutorService threadPool = Executors.newFixedThreadPool(5);
(2)建立只有一個線程的線程池,corePoolSize等maximumPoolSize而且都等於1
ExecutorService threadPool2 = Executors.newSingleThreadExecutor();
(3)建立一個可緩存線程池,corePoolSize等於0,maximumPoolSize等於Integer.MAX_VALUE
ExecutorService threadPool3 = Executors.newCachedThreadPool();

三、底層建立線程的方法詳解
Java底層建立線程池的源碼函數

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.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

corePoolSize:線程池中的常駐核心線程數this

maximumPoolSize:線程池中可以容納的最大線程數線程

keepAliveTime:空餘線程的存好時間,當線程池的數量超過code

corePoolSize時,空閒時間達到keepAliveTime時,多餘線程就會配銷燬直到只剩餘到corePoolSize的數量隊列

TimeUnit:keepAliveTime的時間單位資源

workQueue:任務隊列,當corePoolSize線程沒有空閒的時候,不會立刻擴充線程池的線程數,而是先將任務存放到workQueue中get

threadFactory:常見線程池中的線程的線程工廠源碼

handler:拒絕策略,當隊列滿了,且工做線程大於等於maximumPoolSize時,如何來拒絕請求執行的策略,Java中拒絕策略有四種,分別爲AbortPolicy,默認拒絕策略,直接拋出
RejectedExecutionException 異常阻止系統正常運行;
DiscardPolicy,默默的丟棄沒法處理的任務;DiscardOldestPolicy,丟棄隊列中等待最久的任務;CallerRunsPolicy,調用者運行「一種調節機制,該策略就不會拋棄任務,也不會拋出異常,而是將某些任務回退給調用者

四、推薦使用的建立線程池的方式
上面的三種建立的三種線程池的方式,都推薦,推薦自定義線程池,緣由請看源碼,源碼以下

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

前兩種隊列使用了LinkedBlockingQueue,而LinkedBlockingQueue從默認構造函數是

public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

它能夠存儲Integer.MAX_VALUE個任務,若是系統一直提交任務,而系統又處理緩慢容易引起OOM異常
後一個更不用說能夠最大線程數能夠建立到Integer.MAX_VALUE個線程更容易引起OOM異常,因此纔要自定義線程池
五、自定義一個線程池

ExecutorService threadPool4 = new ThreadPoolExecutor(
                5,
                Runtime.getRuntime().availableProcessors()+1,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(9),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());
相關文章
相關標籤/搜索