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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ScheduleThreadPoolExecutor的工作原理与使用示例

發(fā)布時間:2025/7/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ScheduleThreadPoolExecutor的工作原理与使用示例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

歡迎探討,如有錯誤敬請指正

如需轉載,請注明出處? http://www.cnblogs.com/nullzx/


?

1. ScheduleExecutorService接口、ScheduledFuture接口

從圖中可以看出ScheduledExecutorService接口繼承了ExecutorService接口,同時還添加了有關提交定時任務的四個方法。

public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) //向定時任務線程池提交一個延時Runnable任務(僅執(zhí)行一次) public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit); //向定時任務線程池提交一個延時的Callable任務(僅執(zhí)行一次) public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) //向定時任務線程池提交一個固定時間間隔執(zhí)行的任務 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,long delay, TimeUnit unit); //向定時任務線程池提交一個固定延時間隔執(zhí)行的任務

固定時間間隔的任務不論每次任務花費多少時間,下次任務開始執(zhí)行時間是確定的,當然執(zhí)行任務的時間不能超過執(zhí)行周期。

固定延時間隔的任務是指每次執(zhí)行完任務以后都延時一個固定的時間。由于操作系統(tǒng)調(diào)度以及每次任務執(zhí)行的語句可能不同,所以每次任務執(zhí)行所花費的時間是不確定的,也就導致了每次任務的執(zhí)行周期存在一定的波動。

注意:定時或延時任務中所涉及到時間、周期不能保證實時性及準確性,實際運行中會有一定的誤差。

從上圖可以還可以看出ScheduledThreadPoolExecutor還直接繼承了ThreadPoolExecutor。這樣做是為了利用ThreadPoolExecutor已實現(xiàn)的方法。

可以向定時任務線程池提交普通任務。對于定時任務線程池而言,普通任務只不過是延時執(zhí)行時間為0,周期為0的任務。

從上述四個方法中的返回值可以看出,當向線程池提交任務時會返回一個ScheduleFuture接口的對象。通過下圖可以看出,ScheduledFuture接口繼承了Delayed和Future接口。我們可以通過ScheduleFutured對象的cancel方法可以結束一個定時任務。

?

在ScheduledThreadPoolExecutor中阻塞隊列存儲的是ScheduledFutureTask對象,它是任務真正的載體。但是ScheduledFutureTask對象同樣可以看做Runnable對象,所以同樣可以使用ThreadPoolExecutor中的方法來處理它。

2. ScheduledThreadPoolExecutor的運行原理

在圖中,我們將ScheduleFutureTask簡稱為SFT

在定時任務線程池中存儲任務的隊列是具有優(yōu)先性質(zhì)的阻塞隊列。在這個隊列中離下次執(zhí)行時間最近的任務位于隊首(關于優(yōu)先隊列的原理請參照本博客后續(xù)數(shù)據(jù)結構的相關內(nèi)容)。線程每次通過優(yōu)先隊列的take方法獲取任務。如果隊列為空take方法阻塞,否則take方法從隊首獲取帶執(zhí)行的任務(即ScheduleFutureTask對象),然后從任務的getDelay方法獲取應當延時的時間,再通過帶參數(shù)的await方法進行延時。當延時時間已到,則開始執(zhí)行任務(在執(zhí)行之前還要檢測這個任務是否已被取消),執(zhí)行完畢以后繼續(xù)判斷這是否是一個周期任務。如果不是,調(diào)用take方法獲取新任務,重復上述操作。如果是計算下一次執(zhí)行的時間,然后調(diào)用隊列的add方法將這個任務再次入列。入列完成后,繼續(xù)調(diào)用take方法獲取新任務,這樣重復的執(zhí)行下去。

以上就是定時任務線程池工作的最基本原理,實際上take、add、任務的取消等過程比較復雜,圖中也沒有說明線程在執(zhí)行await方法時隊首元素改變時的情況。如果想繼續(xù)了解,請參閱本博客“ScheduledThreadPoolExecutor源代碼分析”的文章。

3. ScheduleThreadPoolExecutor與Timer相比的優(yōu)勢。

(1)Timer是基于絕對時間的延時執(zhí)行或周期執(zhí)行,當系統(tǒng)時間改變,則任務的執(zhí)行會受到的影響。而ScheduleThreadPoolExecutore中,任務時基于相對時間進行周期或延時操作。

(2)Timer也可以提交多個TimeTask任務,但只有一個線程來執(zhí)行所有的TimeTask,這樣并發(fā)性受到影響。而ScheduleThreadPoolExecutore可以設定池中線程的數(shù)量。

(3)Timer不會捕獲TimerTask的異常,只是簡單地停止,這樣勢必會影響其他TimeTask的執(zhí)行。而ScheduleThreadPoolExecutore中,如果一個線程因某些原因停止,線程池可以自動創(chuàng)建新的線程來維護池中線程的數(shù)量。

4. 使用示例

package javaleanning;import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit;public class ScheduledThreadPoolExecutorDemo {static class TimerTask implements Runnable{private String id;public TimerTask(String id){this.id = id;}@Overridepublic void run(){System.out.println(id);}}public static void main(String[] args) throws InterruptedException{ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);ScheduledFuture sfa = ses.scheduleAtFixedRate(new TimerTask("a"), 200,1000, TimeUnit.MILLISECONDS);ScheduledFuture sfb = ses.scheduleAtFixedRate(new TimerTask("b"), 400, 1000, TimeUnit.MILLISECONDS);ScheduledFuture sfc = ses.scheduleAtFixedRate(new TimerTask("c"), 600,1000, TimeUnit.MILLISECONDS);ScheduledFuture sfd = ses.scheduleAtFixedRate(new TimerTask("d"), 800, 1000, TimeUnit.MILLISECONDS);Thread.sleep(5000);sfa.cancel(true);Thread.sleep(5000);ses.shutdown();} }

?在這個示例中,定義了一個內(nèi)部類TimerTask,它實現(xiàn)了Runnable接口。在main方法中創(chuàng)建了一個定時任務線程池,向它提交了四個任務a,b,c,d。四個任務起始的延時時間分別是200ms、400ms、600ms、800ms,執(zhí)行周期都為1000ms。5秒以后取消了定時任務a的執(zhí)行。又過了5秒,關閉了線程池。默認情況下關閉線程池會結束池所有的任務。

以下是運行結果
a
b
c
d
a
b
c
d
a
b
c
d
a
b
c
d
a
b
c
d
b
c
d
b
c
d
b
c
d
b
c
d
b
c
d

5. 參考內(nèi)容

[1] http://janeky.iteye.com/blog/770441

轉載于:https://www.cnblogs.com/nullzx/p/5188890.html

總結

以上是生活随笔為你收集整理的ScheduleThreadPoolExecutor的工作原理与使用示例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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