java四種線程池簡介,使用
阿新 • • 發佈:2018-01-11
參數 有一個 例子 system pre mit time style over
為什麽使用線程池
1.減少了創建和銷毀線程的次數,每個工作線程都可以被重復利用,可執行多個任務。
2.可以根據系統的承受能力,調整線程池中工作線線程的數目,防止消耗過多的內存
線程池流程
ThreadPoolExecutor 屬性: corePoolSize:核心池的大小,這個參數跟後面講述的線程池的實現原理有非常大的關系。在創建了線程池後,默認情況下,線程池中並沒有任何線程,而是等待有任務到來才創建線程去執行任務 maximumPoolSize:線程池最大線程數 keepAliveTime:表示線程沒有任務執行時最多保持多久時間會終止。默認情況下,只有當線程池中的線程數大於corePoolSize時,keepAliveTime才會起作用,直到線程池中的線程數不大於corePoolSize workQueue:一個阻塞隊列,用來存儲等待執行的任務,這個參數的選擇也很重要,會對線程池的運行過程產生重大影響,一般來說,這裏的阻塞隊列有以下幾種選擇:threadFactory:線程工廠,主要用來創建線程; handler:表示當拒絕處理任務時的策略 ThreadPoolExecutor池子的處理流程如下: 1)當池子大小小於corePoolSize就新建線程,並處理請求 2)當池子大小等於corePoolSize,把請求放入workQueue中,池子裏的空閑線程就去從workQueue中取任務並處理 3)當workQueue放不下新入的任務時,新建線程入池,並處理請求,如果池子大小撐到了maximumPoolSize就用RejectedExecutionHandler來做拒絕處理 4)另外,當池子的線程數大於corePoolSize的時候,多余的線程會等待keepAliveTime長的時間,如果無請求可處理就自行銷毀 其會優先創建 CorePoolSiz 線程, 當繼續增加線程時,先放入Queue中,當 CorePoolSiz 和 Queue 都滿的時候,就增加創建新線程,當線程達到MaxPoolSize的時候,就會拋出錯 誤 org.springframework.core.task.TaskRejectedException
四種線程池
其實四種線程池都是 ThreadPoolExecutor ,只是創建參數不同
newSingleThreadExecutor
創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當於單線程串行執行所有任務。如果這個唯一的線程因為異常結束,那麽會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。
newFixedThreadPool
創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那麽線程池會補充一個新線程。
newCachedThreadPool
創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,那麽就會回收部分空閑(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴於操作系統(或者說JVM)能夠創建的最大線程大小。
newScheduledThreadPool
創建一個大小無限的線程池。此線程池支持定時以及周期性執行任務的需求。
例子(CountDownLatch,Future)
1、線程數是5,執行10個任務,執行完畢之後關閉線程池
//使用isTerminated判斷線程是否執行完成 public class Test2 { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(5); for(int i=0;i<10;i++){ executorService.execute(new Runnable() { @Override public void run() { try { System.out.println("線程名稱"+Thread.currentThread().getName()); Thread.sleep(1000*3); System.out.println("線程名稱"+Thread.currentThread().getName()+"結束"); } catch (InterruptedException e) { e.printStackTrace(); } } }); } System.out.println("開始關閉線程池,不再接受新任務"); executorService.shutdown(); System.out.println("===========");
//等待所有線程執行完成 while (!executorService.isTerminated()) { } System.out.println("線程池關閉完成"); } }
//使用CountDownLatch判斷線程是否執行完成 public class Test { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(5); final CountDownLatch countDownLatch = new CountDownLatch(10); for(int i=0;i<10;i++){ executorService.execute(new Runnable() { @Override public void run() { try { System.out.println("線程名稱"+Thread.currentThread().getName()); Thread.sleep(1000*3); System.out.println("線程名稱"+Thread.currentThread().getName()+"結束"); } catch (InterruptedException e) { e.printStackTrace(); }finally { //計數器減一 countDownLatch.countDown(); } } }); } try { //等待所有線程執行結束 countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("開始關閉線程池"); executorService.shutdown(); System.out.println("線程池關閉完成"); } }
//使用Future 得到線程任務返回結果 public class Test { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(5); List<Future<String>> futures = new ArrayList<Future<String>>(); for(int i=0;i<10;i++){ //使用future接受處理結果 Future<String> future = executorService.submit(new Callable<String>() { @Override public String call() throws Exception { System.out.println("線程名稱"+Thread.currentThread().getName()); return Thread.currentThread().getName(); } }); futures.add(future); } try { for(Future<String> future : futures){ //get方法會阻塞當前線程,直到任務執行完成返回結果 System.out.println("返回結果====="+future.get()); } } catch (Exception e) { e.printStackTrace(); } //開始關閉線程池 executorService.shutdown(); System.out.println("線程池關閉完成"); } }
java四種線程池簡介,使用