一、線程池的優點緩存
(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());