1. 程式人生 > >java四種線程池簡介,使用

java四種線程池簡介,使用

參數 有一個 例子 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四種線程池簡介,使用