詳解Java四種線程池

線程在併發程序中用的比較多,建立線程原始的有最基本的建立方式:緩存

public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //todo
            }
        }).start();
    }複製代碼

但若是經過這樣創線程那就有點low了:bash

1)每次經過new Thread()建立對象性能不佳。併發

2)線程缺少統一管理,可能無限制新建線程,相互之間競爭,及可能佔用過多系統資源致使死機或oom。ide

3)缺少更多功能,如定時執行、按期執行、線程中斷。性能

這裏能夠用到Java提供的4種線程池來建立,分別爲:spa

  • newCachedThreadPool建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程。
  • newFixedThreadPool建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
  • newScheduledThreadPool建立一個定長線程池,支持定時及週期性任務執行。
  • newSingleThreadExecutor建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照指定順序(FIFO,LIFO, 優先級)執行。

下面來比較一下這四種線程池:線程

newCachedThreadPlool:

public static void main(String[] args) {
     ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
     for (int i=0; i<10; i++){
         final int index = i;
         try {
             Thread.sleep(1000);
         } catch (InterruptedException e){

         }
         cacheThreadPool.execute(new Runnable() {
             @Override
             public void run() {
                 System.out.println("第" +index +"個線程" +Thread.currentThread().getName());
             }
         });
     }
 }複製代碼

輸出結果爲:code


能夠看出當執行第二個任務時第一個任務已經完成,會複用執行第一個任務的線程,而不用去從新建立線程。cdn

newFixedThreadPool:

public static void main(String[] args) {
    ExecutorService fixedThreadPool =Executors. newFixedThreadPool(3);
    for (int i =1; i<=5;i++){
        final int index=i ;
        fixedThreadPool.execute(new Runnable(){
            @Override
            public void run() {
                try {
                    System.out.println("第" +index + "個線程" +Thread.currentThread().getName());
                    Thread.sleep(1000);
                } catch(InterruptedException e ) {
                    
                }
            }
        });
    }
}複製代碼

fixThreadPool會定義開啓的線程數,例子中開啓了三個,因此結果是前三個線程執行,第4個線程要等待1秒後執行。對象

newScheduledThreadPool:

該線程池能夠安排在給定延遲後運行命令或者按期地執行。

延遲執行示例

//corePoolSize - 池中所保存的線程數,即便線程是空閒的也包括在內。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)複製代碼

public static void main(String[] args) {
    ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);
    scheduledThreadPool.schedule(new Runnable(){
        @Override
        public void run() {
            System.out.println("延遲3秒後執行");
        }
    }, 3, TimeUnit.SECONDS);
}複製代碼

上述實例會在開啓3秒後執行。

按期執行示例

public static void main(String[] args) {
    ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);
    scheduledThreadPool.scheduleAtFixedRate(new Runnable(){
        @Override
        public void run() {
            System.out.println("延遲3秒後執行");
        }
    }, 1, 3, TimeUnit.SECONDS);  //1:initialDelay, 3:period
}複製代碼

上述示例會在開啓後延遲1秒執行,而後每3秒執行一次。

newSingleThreadExecutor:

public static void main(String[] args) {
    ExecutorService singleThreadPool= Executors.newSingleThreadExecutor();
    for(int i=1;i<=5;i++){
        int index=i;
        singleThreadPool.execute(new Runnable(){
            @Override
            public void run() {
                try{
                    System.out.println("第"+index+"個線程");
                    Thread.sleep(2000);
                }catch(InterruptedException e) {
                    e.printStackTrace();
                }
            } });
    }
}複製代碼


會每2秒創一個線程,並且是順序的執行各個任務,而且在任意給定的時間不會有多個線程是活動的,其實與newFixedThreadPool(1)效果是同樣的。

相關文章
相關標籤/搜索