日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[转]javaandroid线程池

發(fā)布時間:2023/12/4 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转]javaandroid线程池 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

java多線程-概念&創(chuàng)建啟動&中斷&守護線程&優(yōu)先級&線程狀態(tài)(多線程編程之一)
java多線程同步以及線程間通信詳解&消費者生產(chǎn)者模式&死鎖&Thread.join()(多線程編程之二)
java&android線程池-Executor框架之ThreadPoolExcutor&ScheduledThreadPoolExecutor淺析(多線程編程之三)
Java多線程:Callable、Future和FutureTask淺析(多線程編程之四)
?

無論是在java還是在android中其實使用到的線程池都基本是一樣的,因此本篇我們將來認(rèn)識一下線程池Executor框架(相關(guān)知識點結(jié)合了并發(fā)編程藝術(shù)書以及Android開發(fā)藝術(shù)探索而總結(jié)),下面是本篇的主要知識點:

?

1.Executor框架淺析? 首先我們得明白一個 問題,為什么需要線程池?在java中,使用線程來執(zhí)行異步任務(wù)時,線程的創(chuàng)建和銷毀需要一定的開銷,如果我們?yōu)槊恳粋€任務(wù)創(chuàng)建一個新的線程來執(zhí)行的話,那么這些線程的創(chuàng)建與銷毀將消耗大量的計算資源。同時為每一個任務(wù)創(chuàng)建一個新線程來執(zhí)行,這樣的方式可能會使處于高負(fù)荷狀態(tài)的應(yīng)用最終崩潰。所以線程池的出現(xiàn)為解決這個問題帶來曙光。我們將在線程池中創(chuàng)建若干條線程,當(dāng)有任務(wù)需要執(zhí)行時就從該線程池中獲取一條線程來執(zhí)行任務(wù),如果一時間任務(wù)過多,超出線程池的線程數(shù)量,那么后面的線程任務(wù)就進入一個等待隊列進行等待,直到線程池有線程處于空閑時才從等待隊列獲取要執(zhí)行的任務(wù)進行處理,以此循環(huán).....這樣就大大減少了線程創(chuàng)建和銷毀的開銷,也會緩解我們的應(yīng)用處于超負(fù)荷時的情況。 1.1Executor框架的兩級調(diào)度模型 在java線程啟動時會創(chuàng)建一個本地操作系統(tǒng)線程,當(dāng)該java線程終止時,這個操作系統(tǒng)線程也會被回收。而每一個java線程都會被一對一映射為本地操作系統(tǒng)的線程,操作系統(tǒng)會調(diào)度所有的線程并將它們分別給可用的CPU。而所謂的映射方式是這樣實現(xiàn)的,在上層,java多線程程序通過把應(yīng)用分為若干個任務(wù),然后使用用戶級的調(diào)度器(Executor框架)將這些任務(wù)映射為固定數(shù)量的線程;在底層,操作系統(tǒng)內(nèi)核將這些線程映射到硬件處理器上。這樣種兩級調(diào)度模型如下圖所示:

?

?

從圖中我們可以看出,應(yīng)用程序通過Executor框架控制上層的調(diào)度,而下層的調(diào)度由操作系統(tǒng)內(nèi)核控制,下層的調(diào)度不受應(yīng)用程序的控制。 1.2 Executor框架的結(jié)構(gòu) Executor框架的結(jié)構(gòu)主要包括3個部分 1.任務(wù):包括被執(zhí)行任務(wù)需要實現(xiàn)的接口:Runnable接口或Callable接口 2.任務(wù)的執(zhí)行:包括任務(wù)執(zhí)行機制的核心接口Executor,以及繼承自Executor的EexcutorService接口。Exrcutor有兩個關(guān)鍵類實現(xiàn)了ExecutorService接口(ThreadPoolExecutor和ScheduledThreadPoolExecutor)。 3.異步計算的結(jié)果:包括接口Future和實現(xiàn)Future接口的FutureTask類(這個我們放在下一篇文章說明) 下面我們通過一個UML圖來認(rèn)識一下這些類間的關(guān)系:

?

?

Extecutor是一個接口,它是Executor框架的基礎(chǔ),它將任務(wù)的提交與任務(wù)的執(zhí)行分離開來。 ThreadPoolExecutor是線程池的核心實現(xiàn)類,用來執(zhí)行被提交的任務(wù)。 ScheduledThreadPoolExecutor是一個實現(xiàn)類,可以在給定的延遲后運行命令,或者定期執(zhí)行命令。ScheduledThreadPoolExecutor比Timer更靈活,功能更強大。 Future接口和實現(xiàn)Future接口的FutureTask類,代表異步計算的結(jié)果。 Runnable接口和Callable接口的實現(xiàn)類,都可以被ThreadPoolExecutor或者ScheduledThreadPoolExecutor執(zhí)行。區(qū)別就是Runnable無法返回執(zhí)行結(jié)果,而Callable可以返回執(zhí)行結(jié)果。 下面我們通過一張圖來理解它們間的執(zhí)行關(guān)系:

?

?

分析說明: 主線程首先創(chuàng)建實現(xiàn)Runnable或Callable接口的任務(wù)對象,工具類Executors可以把一個Runnable對象封裝為一個Callable對象,使用如下兩種方式: Executors.callable(Runnable task)或者Executors.callable(Runnable task,Object resule)。 然后可以把Runnable對象直接提交給ExecutorService執(zhí)行,方法為ExecutorService.execute(Runnable command);或者也可以把Runnable對象或者Callable對象提交給ExecutorService執(zhí)行,方法為ExecutorService.submit(Runnable task)或ExecutorService.submit(Callable<T> task)。這里需要注意的是如果執(zhí)行ExecutorService.submit(...),ExecutorService將返回一個實現(xiàn)Future接口的對象(其實就是FutureTask)。當(dāng)然由于FutureTask實現(xiàn)了Runnable接口,我們也可以直接創(chuàng)建FutureTask,然后提交給ExecutorService執(zhí)行。到此Executor框架的主要體系結(jié)構(gòu)我們都介紹完了,我們對此有了大概了解后,下面我們就重點聊聊兩個主要的線程池實現(xiàn)類。 2.ThreadPoolExecutor淺析? ThreadPoolExecutor是線程的真正實現(xiàn),通常使用工廠類Executors來創(chuàng)建,但它的構(gòu)造方法提供了一系列參數(shù)來配置線程池,下面我們就先介紹ThreadPoolExecutor的構(gòu)造方法中各個參數(shù)的含義。 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,threadFactory, defaultHandler);}

corePoolSize:線程池的核心線程數(shù),默認(rèn)情況下,核心線程數(shù)會一直在線程池中存活,即使它們處理閑置狀態(tài)。如果將ThreadPoolExecutor的allowCoreThreadTimeOut屬性設(shè)置為true,那么閑置的核心線程在等待新任務(wù)到來時會執(zhí)行超時策略,這個時間間隔由keepAliveTime所指定,當(dāng)?shù)却龝r間超過keepAliveTime所指定的時長后,核心線程就會被終止。

maximumPoolSize:線程池所能容納的最大線程數(shù)量,當(dāng)活動線程數(shù)到達這個數(shù)值后,后續(xù)的新任務(wù)將會被阻塞。 keepAliveTime:非核心線程閑置時的超時時長,超過這個時長,非核心線程就會被回收。當(dāng)ThreadPoolExecutor的allowCoreThreadTimeOut屬性設(shè)置為true時,keepAliveTime同樣會作用于核心線程。 unit:用于指定keepAliveTime參數(shù)的時間單位,這是一個枚舉,常用的有TimeUnit.MILLISECONDS(毫秒),TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分鐘)等。 workQueue:線程池中的任務(wù)隊列,通過線程池的execute方法提交Runnable對象會存儲在這個隊列中。 threadFactory:線程工廠,為線程池提供創(chuàng)建新線程的功能。ThreadFactory是一個接口,它只有一個方法:Thread newThread(Runnable r)。 除了上面的參數(shù)外還有個不常用的參數(shù),RejectExecutionHandler,這個參數(shù)表示當(dāng)ThreadPoolExecutor已經(jīng)關(guān)閉或者ThreadPoolExecutor已經(jīng)飽和時(達到了最大線程池大小而且工作隊列已經(jīng)滿),execute方法將會調(diào)用Handler的rejectExecution方法來通知調(diào)用者,默認(rèn)情況 下是拋出一個RejectExecutionException異常。了解完相關(guān)構(gòu)造函數(shù)的參數(shù),我們再來看看ThreadPoolExecutor執(zhí)行任務(wù)時的大致規(guī)則: (1)如果線程池的數(shù)量還未達到核心線程的數(shù)量,那么會直接啟動一個核心線程來執(zhí)行任務(wù) (2)如果線程池中的線程數(shù)量已經(jīng)達到或者超出核心線程的數(shù)量,那么任務(wù)會被插入到任務(wù)隊列中排隊等待執(zhí)行。 (3)如果在步驟(2)中無法將任務(wù)插入到任務(wù)隊列中,這往往是由于任務(wù)隊列已滿,這個時候如果線程數(shù)量未達到線程池規(guī)定的最大值,那么會立刻啟動一個非核心線程來執(zhí)行任務(wù)。 (4)如果在步驟(3)中線程數(shù)量已經(jīng)達到線程池規(guī)定的最大值,那么就會拒絕執(zhí)行此任務(wù),ThreadPoolExecutor會調(diào)用RejectExecutionHandler的rejectExecution方法來通知調(diào)用者。 到此ThreadPoolExecutor的詳細(xì)配置了解完了,ThreadPoolExecutor的執(zhí)行規(guī)則也了解完了,那么接下來我們就來介紹3種常見的線程池,它們都直接或者間接地通過配置ThreadPoolExecutor來實現(xiàn)自己的功能特性,這個3種線程池分別是FixedThreadPool,CachedThreadPool,ScheduledThreadPool以及SingleThreadExecutor。 2.1FixedThreadPool FixedThreadPool模式會使用一個優(yōu)先固定數(shù)目的線程來處理若干數(shù)目的任務(wù)。規(guī)定數(shù)目的線程處理所有任務(wù),一旦有線程處理完了任務(wù)就會被用來處理新的任務(wù)(如果有的話)。FixedThreadPool模式下最多的線程數(shù)目是一定的。創(chuàng)建FixedThreadPool對象代碼如下: ExecutorService fixedThreadPool=Executors.newFixedThreadPool(5);

我們來看看FixedThreadPool創(chuàng)建方法源碼:

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

?

FixedThreadPool的corePoolSize和maximumPoolSize參數(shù)都被設(shè)置為nThreads。當(dāng)線程池中的線程數(shù)量大于corePoolSize時,keepAliveTime為非核心空閑線程等待新任務(wù)的最長時間,超過這個時間后非核心線程將被終止,這里keepAliveTime設(shè)置為0L,就說明非核心線程會立即被終止。事實上這里也沒有非核心線程創(chuàng)建,因為核心線程數(shù)和最大線程數(shù)都一樣的。下面我們來看看FixedThreadPool的execute()方法的運行流程:

?

?

分析: (1)如果當(dāng)前運行線程數(shù)少corePoolSize,則創(chuàng)建一個新的線程來執(zhí)行任務(wù)。 (2)如果當(dāng)前線程池的運行線程數(shù)等于corePoolSize,那么后面提交的任務(wù)將加入LinkedBlockingQueue。 (3)線程在執(zhí)行完圖中的1后,會在循環(huán)中反復(fù)從LinkedBlockingQueue獲取任務(wù)來執(zhí)行。 這里還有點要說明的是FixedThreadPool使用的是無界隊列LinkedBlockingQueue作為線程池的工作隊列(隊列容量為Integer.MAX_VALUE)。使用該隊列作為工作隊列會對線程池產(chǎn)生如下影響 (1)當(dāng)前線程池中的線程數(shù)量達到corePoolSize后,新的任務(wù)將在無界隊列中等待。 (2)由于我們使用的是無界隊列,所以參數(shù)maximumPoolSize和keepAliveTime無效。 (3)由于使用無界隊列,運行中的FixedThreadPool不會拒絕任務(wù)(當(dāng)然此時是未執(zhí)行shutdown和shutdownNow方法),所以不會去調(diào)用RejectExecutionHandler的rejectExecution方法拋出異常。 下面我們給出案例,該案例來自java編程思想一書: public class LiftOff implements Runnable{ protected int countDown = 10; //Default private static int taskCount = 0; private final int id = taskCount++; public LiftOff() {} public LiftOff(int countDown) { this.countDown = countDown; } public String status() { return "#" + id + "(" + (countDown > 0 ? countDown : "LiftOff!") + ") "; } @Override public void run() { while(countDown-- > 0) { System.out.print(status()); Thread.yield(); } } }

?

聲明一個Runnable對象,使用FixedThreadPool執(zhí)行任務(wù)如下:

public class FixedThreadPool { public static void main(String[] args) { //三個線程來執(zhí)行五個任務(wù) ExecutorService exec = Executors.newFixedThreadPool(3); for(int i = 0; i < 5; i++) { exec.execute(new LiftOff()); } exec.shutdown(); } } 2.2 CachedThreadPool CachedThreadPool首先會按照需要創(chuàng)建足夠多的線程來執(zhí)行任務(wù)(Task)。隨著程序執(zhí)行的過程,有的線程執(zhí)行完了任務(wù),可以被重新循環(huán)使用時,才不再創(chuàng)建新的線程來執(zhí)行任務(wù)。創(chuàng)建方式: ExecutorService cachedThreadPool=Executors.newCachedThreadPool(); public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());}

?

從該靜態(tài)方法,我們可以看到CachedThreadPool的corePoolSize被設(shè)置為0,而maximumPoolSize被設(shè)置Integer.MAX_VALUE,即maximumPoolSize是無界的,而keepAliveTime被設(shè)置為60L,單位為妙。也就是空閑線程等待時間最長為60秒,超過該時間將會被終止。而且在這里CachedThreadPool使用的是沒有容量的SynchronousQueue作為線程池的工作隊列,但其maximumPoolSize是無界的,也就是意味著如果主線程提交任務(wù)的速度高于maximumPoolSize中線程處理任務(wù)的速度時CachedThreadPool將會不斷的創(chuàng)建新的線程,在極端情況下,CachedThreadPool會因為創(chuàng)建過多線程而耗盡CPU和內(nèi)存資源。CachedThreadPool的execute()方法的運行流程:

?

分析: (1)首先執(zhí)行SynchronousQueue.offer(Runnable task),添加一個任務(wù)。如果當(dāng)前CachedThreadPool中有空閑線程正在執(zhí)行SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS),其中NANOSECONDS是毫微秒即十億分之一秒(就是微秒/1000),那么主線程執(zhí)行offer操作與空閑線程執(zhí)行poll操作配對成功,主線程把任務(wù)交給空閑線程執(zhí)行,execute()方法執(zhí)行完成,否則進入第(2)步。 (2)當(dāng)CachedThreadPool初始線程數(shù)為空時,或者當(dāng)前沒有空閑線程,將沒有線程去執(zhí)行SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS)。這樣的情況下,步驟(1)將會失敗,此時CachedThreadPool會創(chuàng)建一個新的線程來執(zhí)行任務(wù),execute()方法執(zhí)行完成。 (3)在步驟(2)中創(chuàng)建的新線程將任務(wù)執(zhí)行完成后,會執(zhí)行SynchronousQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS),這個poll操作會讓空閑線程最多在SynchronousQueue中等待60秒,如果60秒內(nèi)主線程提交了一個新任務(wù),那么這個空閑線程將會執(zhí)行主線程提交的新任務(wù),否則,這個空閑線程將被終止。由于空閑60秒的空閑線程會被終止,因此長時間保持空閑的?CachedThreadPool是不會使用任何資源的。 根據(jù)前面的分析我們知道SynchronousQueue是一個沒有容量的阻塞隊列(其實個人認(rèn)為是相對應(yīng)時間而已的沒有容量,因為時間到空閑線程就會被移除)。每個插入操作必須等到一個線程與之對應(yīng)。CachedThreadPool使用SynchronousQueue,把主線程的任務(wù)傳遞給空閑線程執(zhí)行。流程如下:


CachedThreadPool使用的案例代碼如下:

public class CachedThreadPool { public static void main(String[] args) { ExecutorService exec = Executors.newCachedThreadPool(); for(int i = 0; i < 10; i++) { exec.execute(new LiftOff()); } exec.shutdown(); } }

?

2.3 SingleThreadExecutor

SingleThreadExecutor模式只會創(chuàng)建一個線程。它和FixedThreadPool比較類似,不過線程數(shù)是一個。如果多個任務(wù)被提交給SingleThreadExecutor的話,那么這些任務(wù)會被保存在一個隊列中,并且會按照任務(wù)提交的順序,一個先執(zhí)行完成再執(zhí)行另外一個線程。SingleThreadExecutor模式可以保證只有一個任務(wù)會被執(zhí)行。這種特點可以被用來處理共享資源的問題而不需要考慮同步的問題。

創(chuàng)建方式: ExecutorService singleThreadExecutor=Executors.newSingleThreadExecutor(); public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));}

?

從靜態(tài)方法可以看出SingleThreadExecutor的corePoolSize和maximumPoolSize被設(shè)置為1,其他參數(shù)則與FixedThreadPool相同。SingleThreadExecutor使用的工作隊列也是無界隊列LinkedBlockingQueue。由于SingleThreadExecutor采用無界隊列的對線程池的影響與FixedThreadPool一樣,這里就不過多描述了。同樣的我們先來看看其運行流程:

?

分析: (1)如果當(dāng)前線程數(shù)少于corePoolSize即線程池中沒有線程運行,則創(chuàng)建一個新的線程來執(zhí)行任務(wù)。 (2)在線程池的線程數(shù)量等于corePoolSize時,將任務(wù)加入到LinkedBlockingQueue。 (3)線程執(zhí)行完成(1)中的任務(wù)后,會在一個無限循環(huán)中反復(fù)從LinkedBlockingQueue獲取任務(wù)來執(zhí)行。 SingleThreadExecutor使用的案例代碼如下: public class SingleThreadExecutor { public static void main(String[] args) { ExecutorService exec = Executors.newSingleThreadExecutor(); for (int i = 0; i < 2; i++) { exec.execute(new LiftOff()); } } }

?

2.4 各自的適用場景 FixedThreadPool:適用于為了滿足資源管理需求,而需要限制當(dāng)前線程的數(shù)量的應(yīng)用場景,它適用于負(fù)載比較重的服務(wù)器。 SingleThreadExecutor:適用于需要保證執(zhí)行順序地執(zhí)行各個任務(wù);并且在任意時間點,不會有多個線程是活動的場景。 CachedThreadPool:大小無界的線程池,適用于執(zhí)行很多的短期異步任務(wù)的小程序,或者負(fù)載較輕的服務(wù)器。 3.ScheduledThreadPoolExecutor淺析? 3.1 ScheduledThreadPoolExecutor執(zhí)行機制分析 ScheduledThreadPoolExecutor繼承自ThreadPoolExecutor。它主要用來在給定的延遲之后執(zhí)行任務(wù),或者定期執(zhí)行任務(wù)。ScheduledThreadPoolExecutor的功能與Timer類似,但比Timer更強大,更靈活,Timer對應(yīng)的是單個后臺線程,而ScheduledThreadPoolExecutor可以在構(gòu)造函數(shù)中指定多個對應(yīng)的后臺線程數(shù)。接下來我們先來了解一下ScheduledThreadPoolExecutor的運行機制:

?

分析:DelayQueue是一個無界隊列,所以ThreadPoolExecutor的maximumPoolSize在ScheduledThreadPoolExecutor中無意義。ScheduledThreadPoolExecutor的執(zhí)行主要分為以下兩個部分 (1)當(dāng)調(diào)用ScheduledThreadPoolExecutor的scheduleAtFixedRate()方法或者scheduleWithFixedDelay()方法時,會向ScheduledThreadPoolExecutor的DelayQueue添加一個實現(xiàn)了RunnableScheduledFuture接口的ScheduleFutureTask。 (2)線程池中的線程從DelayQueue中獲取ScheduleFutureTask,然后執(zhí)行任務(wù)。 3.2 如何創(chuàng)建ScheduledThreadPoolExecutor? ScheduledThreadPoolExecutor通常使用工廠類Executors來創(chuàng)建,Executors可以創(chuàng)建兩種類型的ScheduledThreadPoolExecutor,如下: (1)ScheduledThreadPoolExecutor:可以執(zhí)行并行任務(wù)也就是多條線程同時執(zhí)行。 (2)SingleThreadScheduledExecutor:可以執(zhí)行單條線程。 創(chuàng)建ScheduledThreadPoolExecutor的方法構(gòu)造如下: public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)

創(chuàng)建SingleThreadScheduledExecutor的方法構(gòu)造如下:

public static ScheduledExecutorService newSingleThreadScheduledExecutor() public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)

創(chuàng)建實例對象代碼如下:

ScheduledExecutorService scheduledThreadPoolExecutor=Executors.newScheduledThreadPool(5); ScheduledExecutorService singleThreadScheduledExecutor=Executors.newSingleThreadScheduledExecutor(); 3.3 ScheduledThreadPoolExecutor和SingleThreadScheduledExecutor的適用場景 ScheduledThreadPoolExecutor:適用于多個后臺線程執(zhí)行周期性任務(wù),同時為了滿足資源管理的需求而需要限制后臺線程數(shù)量的應(yīng)用場景。 SingleThreadScheduledExecutor:適用于需要單個后臺線程執(zhí)行周期任務(wù),同時需要保證任務(wù)順序執(zhí)行的應(yīng)用場景。 3.4 ScheduledThreadPoolExecutor使用案例 我們創(chuàng)建一個Runnable的對象,然后使用ScheduledThreadPoolExecutor的Scheduled()來執(zhí)行延遲任務(wù),輸出執(zhí)行時間即可: 我們先來介紹一下該類延遲執(zhí)行的方法: public ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit); 參數(shù)解析: command:就是一個實現(xiàn)Runnable接口的類 delay:延遲多久后執(zhí)行。 unit:用于指定keepAliveTime參數(shù)的時間單位,這是一個枚舉,常用的有TimeUnit.MILLISECONDS(毫秒),TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分鐘)等。 這里要注意這個方法會返回ScheduledFuture實例,可以用于獲取線程狀態(tài)信息和延遲時間。 package com.zejian.Executor; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; /*** @author zejian* @time 2016年3月14日 下午9:10:41* @decrition 創(chuàng)建一個工作線程繼承Runnable*/ public class WorkerThread implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+" Start. Time = "+getNowDate());threadSleep();System.out.println(Thread.currentThread().getName()+" End. Time = "+getNowDate());}/*** 睡3秒*/public void threadSleep(){try {Thread.sleep(3000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 獲取現(xiàn)在時間* * @return 返回時間類型 yyyy-MM-dd HH:mm:ss*/public static String getNowDate() {Date currentTime = new Date();SimpleDateFormat formatter; formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); String ctime = formatter.format(currentTime); return ctime;} }

?

執(zhí)行類如下:

package com.zejian.Executor; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /*** @author zejian* @time 2016年3月14日 下午9:27:06* @decrition 執(zhí)行類*/ public class ScheduledThreadPoolTest {public static void main(String[] args) {ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);try {//schedule to run after sometimeSystem.out.println("Current Time = "+getNowDate());for(int i=0; i<3; i++){Thread.sleep(1000);WorkerThread worker = new WorkerThread();//延遲10秒后執(zhí)行scheduledThreadPool.schedule(worker, 10, TimeUnit.SECONDS);}Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}scheduledThreadPool.shutdown();while(!scheduledThreadPool.isTerminated()){//wait for all tasks to finish}System.out.println("Finished all threads");}/*** 獲取現(xiàn)在時間* * @return 返回時間類型 yyyy-MM-dd HH:mm:ss*/public static String getNowDate() {Date currentTime = new Date();SimpleDateFormat formatter; formatter = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss"); String ctime = formatter.format(currentTime); return ctime;} }

運行輸入執(zhí)行結(jié)果:

?


線程任務(wù)確實在10秒延遲后才開始執(zhí)行。這就是schedule()方法的使用。下面我們再介紹2個可用于周期性執(zhí)行任務(wù)的方法。

public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnit unit)

scheduleAtFixedRate方法的作用是預(yù)定在初始的延遲結(jié)束后,周期性地執(zhí)行給定的任務(wù),周期長度為period,其中initialDelay為初始延遲。

按照固定的時間來執(zhí)行,即:到點執(zhí)行

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnit unit); scheduleWithFixedDelay方法的作用是預(yù)定在初始的延遲結(jié)束后周期性地執(zhí)行給定任務(wù),在一次調(diào)用完成和下一次調(diào)用開始之間有長度為delay的延遲,其中initialDelay為初始延遲(簡單說是是等上一個任務(wù)結(jié)束后,在等固定的時間,然后執(zhí)行。即:執(zhí)行完上一個任務(wù)后再執(zhí)行)。 下面給出實現(xiàn)案例代碼參考: package com.zejian.Executor; import java.util.Date; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; /*** @author zejian* @time 2016年3月14日 下午10:05:07* @decrition 周期函數(shù)測試類*/ public class ScheduledTask {public ScheduledThreadPoolExecutor se = new ScheduledThreadPoolExecutor(5);public static void main(String[] args) {new ScheduledTask();}public void fixedPeriodSchedule() {// 設(shè)定可以循環(huán)執(zhí)行的runnable,初始延遲為0,這里設(shè)置的任務(wù)的間隔為5秒for(int i=0;i<5;i++){se.scheduleAtFixedRate(new FixedSchedule(), 0, 5, TimeUnit.SECONDS);}}public ScheduledTask() {fixedPeriodSchedule();}class FixedSchedule implements Runnable {public void run() {System.out.println("當(dāng)前線程:"+Thread.currentThread().getName()+" 當(dāng)前時間:"+new Date(System.currentTimeMillis()));}} }

?

運行結(jié)果(后來補貼的結(jié)果,所以時間是2017) 當(dāng)前線程:pool-1-thread-5 當(dāng)前時間:Tue Aug 08 09:43:18 CST 2017 當(dāng)前線程:pool-1-thread-4 當(dāng)前時間:Tue Aug 08 09:43:18 CST 2017 當(dāng)前線程:pool-1-thread-3 當(dāng)前時間:Tue Aug 08 09:43:18 CST 2017 當(dāng)前線程:pool-1-thread-1 當(dāng)前時間:Tue Aug 08 09:43:18 CST 2017 當(dāng)前線程:pool-1-thread-2 當(dāng)前時間:Tue Aug 08 09:43:18 CST 2017 當(dāng)前線程:pool-1-thread-1 當(dāng)前時間:Tue Aug 08 09:43:23 CST 2017 當(dāng)前線程:pool-1-thread-4 當(dāng)前時間:Tue Aug 08 09:43:23 CST 2017 當(dāng)前線程:pool-1-thread-3 當(dāng)前時間:Tue Aug 08 09:43:23 CST 2017 當(dāng)前線程:pool-1-thread-5 當(dāng)前時間:Tue Aug 08 09:43:23 CST 2017 當(dāng)前線程:pool-1-thread-2 當(dāng)前時間:Tue Aug 08 09:43:23 CST 2017 當(dāng)前線程:pool-1-thread-1 當(dāng)前時間:Tue Aug 08 09:43:28 CST 2017 當(dāng)前線程:pool-1-thread-4 當(dāng)前時間:Tue Aug 08 09:43:28 CST 2017 當(dāng)前線程:pool-1-thread-5 當(dāng)前時間:Tue Aug 08 09:43:28 CST 2017 當(dāng)前線程:pool-1-thread-3 當(dāng)前時間:Tue Aug 08 09:43:28 CST 2017 當(dāng)前線程:pool-1-thread-1 當(dāng)前時間:Tue Aug 08 09:43:28 CST 2017

?

至于scheduleWithFixedDelay方法,大家就把代碼稍微修改一下執(zhí)行試試就行,這里就不重復(fù)了。而SingleThreadScheduledExecutor的使用的方法基本是類似,只不過是單線程罷了,這里也不再描述了。好了,今天就到這吧。


主要參考書籍:

?

java核心技術(shù)卷1

android開發(fā)藝術(shù)探索

java并發(fā)編程的藝術(shù)


---------------------
作者:zejian_
來源:CSDN
原文:https://blog.csdn.net/javazejian/article/details/50890554
版權(quán)聲明:本文為作者原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!
內(nèi)容解析By:CSDN,CNBLOG博客文章一鍵轉(zhuǎn)載插件

總結(jié)

以上是生活随笔為你收集整理的[转]javaandroid线程池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。