實戰Java高併發程序設計-05 Java併發包線程池

概念

線程的創建與銷燬都需要銷燬資源,爲了避免頻繁的創建與銷燬線程,可以讓創建的線程進行復用。類似數據庫連接池的概念,

Java中的線程池

Java通過Executors提供四種線程池,分別爲:
newCachedThreadPool創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閒線程,若無可回收,則新建線程。
newFixedThreadPool 創建一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
newScheduledThreadPool 創建一個定長線程池,支持定時及週期性任務執行。
newSingleThreadExecutor 創建一個單線程化的線程池,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。

緩存線程池(CachedThreadPool )

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            try {
                Thread.sleep(index * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            cachedThreadPool.execute(new Runnable() {
                public void run() {
                    System.out.println(Thread.currentThread().getId() + " : " + index);
                }
            });
        }
        cachedThreadPool.shutdown();
    }
}

打印結果發現 執行上一個線程處理的過來打印,所以都是同一個線程完成任務.

9 : 0
9 : 1
9 : 2
9 : 3
9 : 4
9 : 5
9 : 6
9 : 7
9 : 8
9 : 9
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            final int index = i;
            cachedThreadPool.execute(new Runnable() {
                public void run() {
                    System.out.println(Thread.currentThread().getId() + " : " + index);
                }
            });
        }
        cachedThreadPool.shutdown();
    }
}

打印結果,發現當前線程池的線程處理不過來,自動創建新的線程來做處理

9 : 0
12 : 3
10 : 1
11 : 2
14 : 5
15 : 6
13 : 4
16 : 7
14 : 8
16 : 9

定長線程池(FixedThreadPool)

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 10; i++) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getId() + " : " + index);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        fixedThreadPool.shutdown();
    }
}

打印結果 始終只有三個線程處理,沒有來得及處理的排隊等待

9 : 0
10 : 1
11 : 2
10 : 3
11 : 5
9 : 4
11 : 6
9 : 8
10 : 7
10 : 9

調度計劃線程池(ScheduledThreadPool)

三秒鐘之後開始執行,執行完畢就關閉,不循環

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        //三秒後執行
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        scheduledThreadPool.schedule(new Runnable() {
            public void run() {
                System.out.println("delay 3 seconds");
            }
        }, 3, TimeUnit.SECONDS);

        scheduledThreadPool.shutdown();
    }
}
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(10);
        scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getId() + " : delay 3 seconds, and excute every 2 seconds");
            }
        }, 3, 2, TimeUnit.SECONDS);
    }
}

打印結果: 三秒後開始執行打印,之後沒兩秒執行一次,不斷輪詢,每次執行的線程不固定

9 : delay 3 seconds, and excute every 2 seconds
9 : delay 3 seconds, and excute every 2 seconds
11 : delay 3 seconds, and excute every 2 seconds
9 : delay 3 seconds, and excute every 2 seconds
12 : delay 3 seconds, and excute every 2 seconds
11 : delay 3 seconds, and excute every 2 seconds
13 : delay 3 seconds, and excute every 2 seconds
9 : delay 3 seconds, and excute every 2 seconds

單線程線程池(SingleThreadExecutor)

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadPoolExecutorTest {
    public static void main(String[] args) {
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 20; i++) {
            final int index = i;
            singleThreadExecutor.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getId() + " : " + index);
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

打印結果: 發現每次都是同一個線程執行

9 : 0
9 : 1
9 : 2
9 : 3
9 : 4
9 : 5
9 : 6
9 : 7
9 : 8
9 : 9
9 : 10
9 : 11
9 : 12
9 : 13
9 : 14
9 : 15
9 : 16
9 : 17
9 : 18
9 : 19

自定義線程池(ThreadPoolExecutor)

說明

上面四種線程池除了(ScheduledThreadPool)外都繼承與ThreadPoolExecutor類,只不過傳遞的參數不同而已.

這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述
ThreadPoolExecutor的構造函數如下

corePoolSize:指定線程池中線程數量
maximumPoolSize : 指定線程池中最大線程數
keepAliveTime : 當線程池線程數量超過corePoolSize時,多餘的空閒線程存活時間.
unit : keepAliveTime 參數的單位
workQueue : 任務隊列,被加入進來執行的任務,但是未被執行的任務隊列


 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {

自定義線程池

上面既然發現jdk提供的線程池來自於ThreadPoolExecutor,
那麼一樣可以自定義

ExecutorService singleThreadExecutor = new ThreadPoolExecutor(10, 10, 0, TimeUnit.DAYS, 
                new LinkedBlockingQueue<Runnable>(),new ThreadFactory() {

            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                return t;
            }
        });

擴展線程池

執行之前,結束之後,終止調用的方法.


        ExecutorService es = new ThreadPoolExecutor(10, 10, 0, TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>()){

            @Override
            protected void beforeExecute(Thread t, Runnable r) {
                super.beforeExecute(t, r);
            }

            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
            }

            @Override
            protected void terminated() {
                super.terminated();
            }

        };
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章