Spring集成Quartz---Executor框架


ThreadPool衍生開來將還有一個特定的Executor框架。下文將詳細展開講。

1.Executor框架簡介

1.1 概述

在程序運行過程中,創建和銷燬線程需要一定的開銷,因此如果我們爲每一個任務創建一個新線程來執行,這些線程的創建及銷燬將消耗大量的計算機資源。尤其是在線程任務不是特別重的情況下,系統的資源有可能極大的耗費在線程的創建與銷燬上。

因此,我們需要一種容器去集中的管理這些線程,使得已有的線程能夠得到統一的管理和複用。

Java的線程既是工作單元,又是執行機制。從JDK5開始,把工作單元和執行機制分離開來。工作單元包括Runnable和Callable(即實現了這兩個接口的類),而執行機制則由Executor框架提供(提供兩種典型的線程池:ThreadPoolExecutor和ScheduleThreadPoolExecutor作爲工作單元的執行機制)。

1.2 工作單元

在Executor框架中,工作單元其實就是一個實現了Runnable接口或者Callable接口的普通類,該類必須實現對應的run()方法或者call()方法,而該類的實例化對象即爲一個工作單元,可以作爲任務提交給線程池,由線程池創建相應的線程去執行這個工作單元。


1.3 執行機制

有了上文對工作單元的闡釋,執行機制就相對好理解一些,他的本質就是一個線程池,每當有工作單元提交時,線程池需要及時接收這些工作單元,並在後續步驟中,創建相應的線程去執行這些工作單元。同時線程池還需要對這些線程進行統一的管理:創建和銷燬。


1.4 Executor二級調度模型

Executor二級調度模型如下圖所示。


如上圖所示(上圖來源於《Java併發編程的藝術》),兩級調度模型中,OSKernel(操作系統內核)以上爲上級,以下爲下級。

在上級中,一個個任務其實就代表着工作單元,這些工作單元通過Executor交由執行機制進行處理。通常Java多線程程序會把應用分解爲若干個任務,然後使用用戶級的調度器(Executor框架)將這些任務映射爲固定數量的線程;
在下級中,操作系統內核將上層線程映射到硬件處理器上。
從上圖可以看出,應用程序通過Executor框架控制上層的調度;而下層的調度由操作系統內核控制,下層的調度不受應用程序的控制。他只需要完成對線程的一一映射即可。

2.Executor類成員詳解

2.1 成員分類

在Executor框架中,主要的成員可以分爲三類。
第一類,即任務,任務是工作的基本單元,離開任務,整個框架就失去了存在的意義。包括被執行的任務需要實現的Runnable或者Callable接口。

第二類,任務調度,有了任務還不行,必須要有相應的執行機制去執行這些任務。包括任務執行的核心接口Executor接口,以及繼承自Executor接口的ExecutorService接口。Executor框架有兩個關鍵的實現類實現了ExecutorService接口(ThreadPoolExecutor和ScheduleThreadPoolExecutor

第三類,異步計算的結果,任務交由任務調度執行之後,返回的結果稱爲異步計算的結果。這裏涉及到的同步異步的概念,可以參考相應的百度百科,因爲異步不會導致線程阻塞,較爲高效,因此咋Executor框架中,採用異步計算的結果。包括接口Future和實現了Future接口的FutureTask類及ScheduleFutureTask(配合ScheduleThreadPoolExecutor使用)。

整個Executor框架的類成員圖如下所示。


由上圖,可知。
左側以FutureTask爲主線的類是異步計算結。右側的類則爲線程池。

3.ThreadPoolExecutor線程池詳解 

可參考Java併發編程:線程池的使用


這裏補充一些ThreadPoolExecutor線程池的使用場景。
Executor可以創建三種不同類型的ThreadPoolExecutor,都是通過ExecutorService提供的靜態方法進行創建和初始化:
1. FixedThreadPoolExecutor。表示創建固定數量的線程的線程池,即創建一個可複用固定數量線程的線程池,同時採用無界隊列去存放提交的任務。源碼如下:
 /**
     * Creates a thread pool that reuses a fixed number of threads
     * operating off a shared unbounded queue, using the provided
     * ThreadFactory to create new threads when needed.  At any point,
     * at most {@code nThreads} threads will be active processing
     * tasks.  If additional tasks are submitted when all threads are
     * active, they will wait in the queue until a thread is
     * available.  If any thread terminates due to a failure during
     * execution prior to shutdown, a new one will take its place if
     * needed to execute subsequent tasks.  The threads in the pool will
     * exist until it is explicitly {@link ExecutorService#shutdown
     * shutdown}.
     *
     * @param nThreads the number of threads in the pool
     * @param threadFactory the factory to use when creating new threads
     * @return the newly created thread pool
     * @throws NullPointerException if threadFactory is null
     * @throws IllegalArgumentException if {@code nThreads <= 0}
     */
    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }
這裏注意參數 nThreads,表示初始化過程中指定的CorePoolSize。該線程池適用於爲了滿足資源管理需求,而需要現在當前線程數量的應用場景,適用於負載比較重的服務器。

2. SingleThreadPoolExecutor。表示創建一個使用單一工作線程的線程池,適用於需要保證順序的執行各個任務;並且在任意時間點,不會有多個線程是活動的應用場景。源碼如下:
/**
     * Creates an Executor that uses a single worker thread operating
     * off an unbounded queue. (Note however that if this single
     * thread terminates due to a failure during execution prior to
     * shutdown, a new one will take its place if needed to execute
     * subsequent tasks.)  Tasks are guaranteed to execute
     * sequentially, and no more than one task will be active at any
     * given time. Unlike the otherwise equivalent
     * {@code newFixedThreadPool(1)} the returned executor is
     * guaranteed not to be reconfigurable to use additional threads.
     *
     * @return the newly created single-threaded Executor
     */
    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
3. CacheThreadPoolExecutor。該線程池是大小無界的線程池,適用於執行很多短期異步任務的小程序,或者是負載較輕的服務器。源碼如下:
/**
     * Creates a thread pool that creates new threads as needed, but
     * will reuse previously constructed threads when they are
     * available.  These pools will typically improve the performance
     * of programs that execute many short-lived asynchronous tasks.
     * Calls to {@code execute} will reuse previously constructed
     * threads if available. If no existing thread is available, a new
     * thread will be created and added to the pool. Threads that have
     * not been used for sixty seconds are terminated and removed from
     * the cache. Thus, a pool that remains idle for long enough will
     * not consume any resources. Note that pools with similar
     * properties but different details (for example, timeout parameters)
     * may be created using {@link ThreadPoolExecutor} constructors.
     *
     * @return the newly created thread pool
     */
    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

4.ScheduleThreadPoolExecutor線程池詳解

該部分內容篇幅較長,將獨立出一章章節進行闡述。
發佈了54 篇原創文章 · 獲贊 87 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章