Executors

1. 介紹

線程池工廠,在實際生產環境中,線程的數量必須得到控制,盲目的大量創建線程對系統性能是有傷害的。

2. 主要方法

2.1 newFixedThreadPool()

​ 該方法返回一個固定線程數量的線程池,該線程池中的線程數量始終不變,當有一個新的任務提交時,線程池中若有空閒線程,則立即執行,若沒有,則新的任務會被暫存在一個任務隊列中,待有線程空閒時,便處理在任務隊列中的任務。

線程數固定,隊列無限大

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

示例:

/**
 * newFixedThreadPool
 * 若任務生產的速度遠遠大於任務處理的速度,阻塞隊列的容量就會一直變大,有可能產生內存溢出
 */
public class Test01 {

    @Test
    public void test01() throws Exception{
        ExecutorService es = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 30; i++) {
            es.execute(() -> {
                System.out.println(Instant.now().getEpochSecond() + " " + Thread.currentThread().getId());
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        Thread.sleep(13000);
    }

}

2.2 newSingleThreadExecutor()

​ 該方法返回一個只有一個線程的線程池。若多餘一個任務被提交到該線程池,任務會被保存在一個任務隊列中,待線程空閒,按先入先出的順序執行隊列中的任務。

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

2.3 newCachedThreadPool()

​ 該方法返回一個可根據實際情況調整線程數量的線程池。線程池的線程數量不確定,但若有空閒線程可以複用,則會優先使用可複用的線程。若所有線程均在工作,又有新的任務提交,則會創建新的線程處理任務。所有線程在當前任務執行完畢後,將返回線程池進行復用。

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

2.4 newSingleThreadScheduledExecutor()

​ 該方法返回一個ScheduledExecutorService對象,線程池大小爲1。ScheduledExecutorService接口在ExecutorService接口之上擴展了在給定時間執行某任務的功能,如在某個固定的延時之後執行,或者週期性執行某個任務。

    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
        return new DelegatedScheduledExecutorService
            (new ScheduledThreadPoolExecutor(1));
    }

2.5 newScheduledThreadPool()

​ 該方法也返回一個ScheduledExecutorService對象,但該線程池可以指定線程數量。

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }

    public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue());
    }

主要有三種用法,實例:

    /**
     * schedule, 在給定的時間,對任務進行一次調度
     *
     * @throws Exception
     */
    @Test
    public void test01() throws Exception {
        ScheduledExecutorService es = Executors.newScheduledThreadPool(3);

        for (int i = 0; i < 10; i++) {
            es.schedule(() -> {
                System.out.println("run start " + Thread.currentThread().getId());
            }, 2, TimeUnit.SECONDS);
        }
        Thread.sleep(10000);
    }


    /**
     * scheduleAtFixedRate 以任務開始爲時間起點,然後每個period週期執行一次任務,
     * 如果執行任務時間超過了週期時間,則任務完成後立即開啓下一次任務
     *
     * 下面例子實際週期變成了5
     *
     * @throws Exception
     */
    @Test
    public void test02() throws Exception {
        ScheduledExecutorService es = Executors.newScheduledThreadPool(3);

        for (int i = 0; i < 1; i++) {
            es.scheduleAtFixedRate(() -> {
                System.out.println("run start " + Instant.now().getEpochSecond() + " " + Thread.currentThread().getId());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, 2, 3, TimeUnit.SECONDS);
        }
        Thread.sleep(20000);
    }


    /**
     * scheduleWithFixedDelay 以上一個任務結束後爲開始計時,delay時間後,下一個線程執行
     *
     * 下面例子實際週期變成了8
     * @throws Exception
     */
    @Test
    public void test03() throws Exception {
        ScheduledExecutorService es = Executors.newScheduledThreadPool(3);

        for (int i = 0; i < 1; i++) {
            es.scheduleWithFixedDelay(() -> {
                System.out.println("run start " + Instant.now().getEpochSecond() + " " + Thread.currentThread().getId());
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, 2, 3, TimeUnit.SECONDS);
        }
        Thread.sleep(20000);
    }

發佈了311 篇原創文章 · 獲贊 114 · 訪問量 39萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章