1. 程式人生 > >Executors提供的四種線程池

Executors提供的四種線程池

bsp max 添加 周期 接口 取代 tac 緩存 executors

Java 5+中的Executor接口定義一個執行線程的工具。它的子類型即線程池接口是ExecutorService。要配置一個線程池是比較復雜的,尤其是對於線程池的原理不是很清楚的情況下,因此在工具類Executors面提供了一些靜態工廠方法,生成一些常用的線程池,如下所示:

- newCachedThreadPool:創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,那麽就會回收部分空閑(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制(Interger. MAX_VALUE,線程池大小完全依賴於操作系統(或者說JVM)能夠創建的最大線程大小。
- newFixedThreadPool

:創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那麽線程池會補充一個新線程。

- newSingleThreadExecutor:創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當於單線程串行執行所有任務。如果這個唯一的線程因為異常結束,那麽會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。
- newScheduledThreadPool:創建一個大小無限的線程池此線程池支持定時以及周期性執行任務的需求

一、newCachedThreadPool

創建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程。

這種類型的線程池特點是:

  • 工作線程的創建數量幾乎沒有限制 [其實也有限制的,數目為Interger. MAX_VALUE (即 2^31-1) ], 這樣可靈活的往線程池中添加線程。
  • 如果長時間沒有往線程池中提交任務,即如果工作線程空閑了指定的時間(默認為1分鐘),則該工作線程將自動終止。終止後,如果你又提交了新的任務,則線程池重新創建一個工作線程。
  • 在使用CachedThreadPool時,一定要註意控制任務的數量,否則,由於大量線程同時運行,很有會造成系統癱瘓。

public class
MyCacheThreadPool { public static void main(String[] args) { //創建一個線程池, 大小為2^31-1 ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; cachedThreadPool.execute(new Runnable() { public void run() { String currentTime = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss").format(new Date()); System.out.println(index + " currentTime=" + currentTime); } }); } } }

結果如下:

技術分享圖片

二、newFixedThreadPool

創建一個指定工作線程數量的線程池。每當提交一個任務就創建一個工作線程,如果工作線程數量達到線程池初始的最大數,則將提交的任務存入到池隊列中

FixedThreadPool是一個典型且優秀的線程池,它具有線程池提高程序效率和節省創建線程時所耗的開銷的優點。但是,在線程池空閑時,即線程池中沒有可運行任務時,它不會釋放工作線程,還會占用一定的系統資源

示例代碼如下:

public class MyFixedThreadPool
{
    public static void main(String[] args)
    {
        //創建一個線程池, 大小為3; 線程數達到最大值後放入隊列中; 若空閑則不會釋放工作線程
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
       for (int i = 0; i < 10; i++)
        {
            final int index = i;
            fixedThreadPool.execute(new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        Thread.sleep(3000);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    String currentTime = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss").format(new Date());
                    System.out.println(index + " currentTime=" + currentTime);
                }
            });
        }
    }
}

結果如下:

技術分享圖片

因為代碼中線程池的最大工作數量設置為3,則把其他多余的線程存放在隊列中,同一個時間最多運行的線程數為3.

三、newSingleThreadExecutor

創建一個單線程化的Executor,即只創建唯一的工作者線程來執行任務,它只會用唯一的工作線程來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行。如果這個線程異常結束,會有另一個取代它,保證順序執行。單工作線程最大的特點是可保證順序地執行各個任務,並且在任意給定的時間不會有多個線程是活動的。

示例代碼如下:

public class MySingleThreadPool
{
    public static void main(String[] args)
    {
        //創建的線程池大小為1, 同一時間只運行一個線程, 按照提交順序來運行
       ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
       for (int i = 0; i < 10; i++)
        {
            final int index = i;
            singleThreadPool.execute(new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        Thread.sleep(3000);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                    String currentTime = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss").format(new Date());
                    System.out.println(index + " currentTime=" + currentTime);
                }
            });
        }
    }
}

運行結果:

技術分享圖片

newSingleThreadExecutor 同一個時間只運行一個線程,按照線程的提交順序執行線程;

四、newScheduleThreadPool

創建一個定長的線程池,而且支持定時的以及周期性的任務執行,支持定時及周期性任務執行。

延遲3秒執行,延遲執行示例代碼如下:

public class MyScheduleThreadPool
{
    public static void main(String[] args)
    {
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
        Runnable runnable1 = new Runnable()  {
            @Override
            public void run()
            {
                String currentTime = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss").format(new Date());
                System.out.println("Runnable-1 currentTime=" + currentTime);
            }
        };
        //延時3秒後執行
      scheduledThreadPool.schedule(runnable1, 3, TimeUnit.SECONDS);

        Runnable runnable2 = new Runnable()  {
            @Override
            public void run()
            {
                String currentTime = new SimpleDateFormat("yyyy-MM-DD HH:mm:ss").format(new Date());
                System.out.println("Runnable-2 currentTime=" + currentTime);
            }
        };
        //開始延時1秒後執行, 然後每隔3秒執行一次
      scheduledThreadPool.scheduleAtFixedRate(runnable2, 1, 3, TimeUnit.SECONDS);
    }
}

結果如下:

技術分享圖片

Executors提供的四種線程池