java併發編程之線程,線程池,ansync線程池源碼解析

前言

java開源長了, 代碼久了,網上對於線程那是衆說紛紜,一直縈繞我心頭的,jdk線程池好仍是spring線程池好?html

結果發現,spring生命週期管理的線程池,其底層就是私有ThreadPoolExecutor類,spring(具體管理ThreadPoolTaskExecutor類)只是對其一種封裝調用而已;java

而咱們平常使用jdk線程池 - Executor框架, ThreadPoolExecutor是Executor框架的核心實現類;spring

說到底,jdk線程池與spring線程池都是在使用ThreadPollExecutor基礎上開發;json

JDK線程

古老的extend,implment Runnable的實現線程的方式就不說了,也就是測試類寫寫緩存

科普下, jdk8 lambda格式方便快捷的使用多線程

new Thread(() -> System.out.println("線程打印...")).start();

ThreadPollExecutor

炒的火熱jdk線程池的的核心實現類。app

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
  • corePoolSize: 核心線程數。默認狀況下線程池是空的,只有有任務提交的時候纔會去建立線程。當運行的線程少於corePoolSize的時候,新建任務將建立核心線程,若是的等於或者大於corePoolSize的時候將不會建立核心線程,建立普通線程。能夠調用prestartAllcoreThread的方法來提早建立並啓動全部的核心線程。
  • maximumPoolSize:線程池所容許的最大的線程數量。當任務隊列滿了的話線程數小於maximumPoolSize的值的話,新建任務仍是會建立新的線程的。
  • keepAliveTime : 非核心線程閒置的超時時間,第一是非核心的線程第二是閒置狀態。調用allowCoreThreadTimeOut的時候該設置也會做用再核心的線程上面。
  • TimeUnit : 超時的時間單位。DAYS(天),HOURS(小時),MINUTES(f分鐘),SECONDS(秒),MILLISECONDS(毫秒).
  • workQueue : 任務隊列(阻塞隊列)。當前線程書大於corePoolSize的大小的時候,會將任務加入阻塞隊列裏面。該隊列是BlockingQueue類型的。
  • ThreadFactory : 線程工場。咱們能夠本身去定義。
  • RejectedExecutionHandler : 飽和策略。這是當任務隊列和線程數都滿了的時候所採起的的對應策略默認是AbordPolicy表示沒法處理新的任務,並拋出RejectedExecutionException異常。
    • CallerRunsPolicy : 用調用者所在的線程來處理任務。
    • DisCardPolicy : 不能執行任務並將任務刪除。
    • DisCardOldesPolicy : 丟棄隊列最近的任務,並執行當前的任務, 會一直執行下去。

Executore類(框架)

經過idea源碼方法看到, Executors類下, 有很多快捷建立線程池方法 (idea查看類方法alt+7), 下面介紹經常使用的5種建立方法;框架

FixedThreadPool

FixedThreadPool是可重的固定線程數的線程池。異步

//建立FixedThreadPool
 Executors.newFixedThreadPool(5);

//建立所須要的參數
  public static ExecutorService newFixedThreadPool(int nThreads) {
 //最後調用的都是ThreadPoolExecutor
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

咱們只須要傳如須要建立的線程的數量,也就是線程池的大小。咱們能夠看到構造方法,傳入的線程的數量就是核心線程的數量。也就是FixedThreadPool會建立固定數量核心線程的線程池,而且這些核心線程不會被回收,任務超過線程的數量將存入隊列中。async

CachedThreadPool

該線程池是根據須要去建立線程的。

//建立緩存線程池
Executors.newCachedThreadPool();
//構造方法
  public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

咱們能夠看出,這裏面的核心線程數是0,而線程的最大值是Integer.Max_VALUE。閒置超時間是一分鐘。默認隊列能夠保證任務順序的執行。CacheThreadPool適合大量的須要當即處理而且耗時較少的任務。

SingleThreadExecutor

該類是使用單個線程的線程池。

//建立方法
  Executors.newSingleThreadExecutor();
  //構造方法
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

corePoolSize和maximumPoolSize都是1,意味着SingleThreadExecutor只有一個核心線程。其餘的參數和FixedThreadPool同樣。若是已經建立了一個線程再來一個任務的時候會將該任務加入到任務隊列裏面,確保了全部任務的執行順序。

ScheduledThreadPool

ScheduledThreadPool是一個能實現定是和週期性任務的線程池。

//建立
 Executors.newScheduledThreadPool(5);
//構造方法
     public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
    }
//最後仍是調用的
ThreadPoolExecutor的構造方法。

當執行任務的時候,會先將任務包裝成ScheduledFutrueTask並添加到DelayedWorkQueue裏面,當沒超過corePoolSize的時候,會建立線程,人後去DelayedWorkQueue隊列裏面去拿任務,並非當即的執行。當執行完任務的時候會將ScheduledFutrueTask中的time變量改成下次要執行的時間並放回DelayedWorkQueue中。

Spring線程池

@Ansync

傳統方式

springContext.xml配置管理, 其線程池生命週期由spring來管理

<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <!-- 核心線程數,默認爲1 -->
    <property name="corePoolSize" value="10" />
    <!-- 最大線程數,默認爲Integer.MAX_VALUE -->
    <property name="maxPoolSize" value="50" />
    <!-- 隊列最大長度,通常須要設置值>=notifyScheduledMainExecutor.maxNum;默認爲Integer.MAX_VALUE
        <property name="queueCapacity" value="1000" /> -->
    <!-- 線程池維護線程所容許的空閒時間,默認爲60s -->
    <property name="keepAliveSeconds" value="300" />
    <!-- 線程池對拒絕任務(無線程可用)的處理策略,目前只支持AbortPolicy、CallerRunsPolicy;默認爲後者 -->
    <property name="rejectedExecutionHandler">
        <!-- AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 -->
        <!-- CallerRunsPolicy:主線程直接執行該任務,執行完以後嘗試添加下一個任務到線程池中,能夠有效下降向線程池內添加任務的速度 -->
        <!-- DiscardOldestPolicy:拋棄舊的任務、暫不支持;會致使被丟棄的任務沒法再次被執行 -->
        <!-- DiscardPolicy:拋棄當前任務、暫不支持;會致使被丟棄的任務沒法再次被執行 -->
        <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" />
    </property>
</bean>

註解方式

註解又分爲 默認非線程池方式,線程池方式,這裏已線程池方式爲例子

<?xml version="1.0" encoding="UTF-8"?>
<!--Spring框架的xml標籤訂義文檔, 可訪問http://www.springframework.org/schema/task/查看最新task組件的xml標籤文檔-->
<beans xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
                http://www.springframework.org/schema/task
                http://www.springframework.org/schema/task/spring-task-3.2.xsd">

    <!--掃描項目實例化@Component,@Service,@Controller修飾的類-->
    <context:component-scan base-package="com.your_app" />

    <!-- 在代碼中@Async不加參數就會使用task:annotation-driven標籤訂義的executor-->
    <task:annotation-driven executor="myExecutor"/>
    <!-- 在代碼中@Async("myExecutor")能夠顯式指定executor爲"myExecutor"-->
    <task:executor id="myExecutor"
               pool-size="5-25"
               queue-capacity="100"
               rejection-policy="CALLER_RUNS"/>
</beans>
@Async
void doSomething(String s) { //能夠帶參數!
    // this will be executed asynchronously
}

 

具體配置歡迎觀看

https://blog.csdn.net/caib1109/article/details/51623089 

 

調用發現,其org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor 類, 源碼查看,

初始化,也是使用ThreadPoolExecutor實現操做,具體指示設置對應的參數值而已;

 

好了 查看到此結束

文章涉及來源:

 

SpringMVC異步處理之@Async(附源代碼 - 單元測試經過)

https://blog.csdn.net/caib1109/article/details/51623089 

JDK提供的幾種線程池比較

http://www.javashuo.com/article/p-thfurkjh-gd.html

Java多線程-五中線程池分析以及AnsyncTask源碼分析

http://www.javashuo.com/article/p-pnplylnr-dt.html

相關文章
相關標籤/搜索