Executor 框架簡介

Executor 框架

Executor 框架簡介

爲了更好的控制多線程,JDK 提供了一套線程框架 Executor,幫助開發人員有限的進行線程控制,它們都在 java.util.concurrent包中,是 JDK 併發包的核心,其中有一個比較重要的類:Executors, 它扮演着線程工廠的角色,我們通過 Executors可以創建特定功能的線程池。

Executors 創建線程池方法

newFixedThreadPool()

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

newSingleThreadExecutor()

newSingleThreadExecutor,該方法會創建一個線程的線程池,若空閒則執行,若沒有空閒線程,則緩存在任務隊列中。

newCachedThreadPool()

newCachedThreadPool,返回一個可以根據實際情況調整線程個數的線程池,不限制最大的線程數量,若有空閒的線程,則執行任務,若無任務則不創建線程,並且每一個空閒線程會在60秒後自動回收

newScheduledThreadPool()

newScheduledThreadPool,返回一個SchededExecutorService對象,但該線程池可以指定線程的數量

更多

通過 ThreadPoolExecutor類去 自定義線程池

Executors工廠類無法滿足我們的需求,我們可以自己去創建自定義的線程池,其實 Executors工廠類裏面的創建線程方法內部都是採用 ThreadPoolExecutor類,這個類可以自定義線程,其構造方法如下

public ThreadPoolExecutor(
    int corePoolSize,//核心線程數
    int maximumPoolSize,//線程池的最大線程數
    long keepAliveTime,//線程池裏面的線程的存活時間
    TimeUnit unit,// 時間單位
    BlockingQueue<Runnable> workQueue,// 當線程池中沒有空閒線程的時候, 存放任務的阻塞隊列
    ThreadFactory threadFactory,// 線程工廠
    RejectedExecutlonHandler handler//當阻塞隊列也滿了的情況下,可以使用 這個處理者
) {
    ...
}

jdk 幫我們實現的 線程池

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

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

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

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

通過 ThreadPoolExecutor類去 自定義線程池 實戰

package cn.istarfinancial.demo;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @Author: huangwenjun
 * @Description:
 * @Date: Created in 14:43  2018/5/15
 **/
public class ThreadTest {

    public static void main(String[] args) throws Exception {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                1, 2, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1));

        Runnable task1 = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("do task 1 and start sleep....");
                    Thread.sleep(1000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Runnable task2 = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("do task 2 and start sleep....");
                    Thread.sleep(1000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Runnable task3 = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("do task 3 and start sleep....");
                    Thread.sleep(1000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Runnable task4 = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("do task 4 and start sleep....");
                    Thread.sleep(1000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        threadPoolExecutor.submit(task1);
        System.out.println("after submit task1,  poolSize :" + threadPoolExecutor.getPoolSize() + ",  queueSize:" + threadPoolExecutor.getQueue().size());
        threadPoolExecutor.submit(task2);
        System.out.println("after submit task2,  poolSize :" + threadPoolExecutor.getPoolSize() + ",  queueSize:" + threadPoolExecutor.getQueue().size());
        threadPoolExecutor.submit(task3);
        System.out.println("after submit task3,  poolSize :" + threadPoolExecutor.getPoolSize() + ",  queueSize:" + threadPoolExecutor.getQueue().size());
//      threadPoolExecutor.submit(task4);
//      System.out.println("after submit task4,  poolSize :" + threadPoolExecutor.getPoolSize() + ",  queueSize:" + threadPoolExecutor.getQueue().size());
    }
}

  • 輸出
after submit task1,  poolSize :1,  queueSize:0
after submit task2,  poolSize :1,  queueSize:1
after submit task3,  poolSize :2,  queueSize:1
do task 1 and start sleep....
do task 3 and start sleep....

結論

// 結論 隨着任務不斷增多 順序如下
// 1 加入的任務 首先交給 核心線程執行,當核心線程耗盡
// 2 將任務 交給指定的阻塞隊列, 當阻塞隊列 耗盡
// 3 將根據指定最大線程數創建線程去執行任務, 當所有線程耗盡
// 4 調用拒絕策略 如果未指定策略,則會拋出異常
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章