Java并发编程之线程定时器ScheduledThreadPoolExecutor解析
定時(shí)器
就是需要周期性的執(zhí)行任務(wù),也叫調(diào)度任務(wù),在JDK中有個(gè)類Timer是支持周期性執(zhí)行,但是這個(gè)類不建議使用了。
ScheduledThreadPoolExecutor
繼承自ThreadPoolExecutor線程池,在Executors默認(rèn)創(chuàng)建了兩種:
newSingleThreadScheduledExecutor:只包含一個(gè)線程,只需要單個(gè)線程執(zhí)行周期任務(wù),保證順序的執(zhí)行各個(gè)任務(wù)。
newScheduledThreadPool: 可以包含多個(gè)線程的,線程執(zhí)行周期任務(wù),適度控制后臺(tái)線程數(shù)量的時(shí)候。
方法:
schedule:只執(zhí)行一次,任務(wù)還可以延時(shí)執(zhí)行
scheduleAtFixedRate:提交固定時(shí)間間隔的任務(wù)
scheduleWithFixedDelay:提交固定延時(shí)間隔執(zhí)行的任務(wù)
兩者的區(qū)別:間隔的時(shí)間定義不一樣
建議在提交給ScheduledThreadPoolExecutor的任務(wù)要住catch異常。否則不能周期性執(zhí)行任務(wù)。
基本原理
在之前將BlockingQueue<T>的時(shí)候有個(gè)叫DelayQueue<E extends Delayed>堵塞隊(duì)列,這個(gè)就是實(shí)現(xiàn)延遲執(zhí)行,在ScheduledThreadPoolExecutor實(shí)現(xiàn)時(shí)間間隔執(zhí)行的原理與DelayQueue原理差不多
在ScheduledThreadPoolExecutor中有個(gè)靜態(tài)類DelayedWorkQueue,該類也是一個(gè)延時(shí)隊(duì)列。
構(gòu)造方法是調(diào)用了父類構(gòu)造,將隊(duì)列換成了延時(shí)隊(duì)列DelayedWorkQueue
public ScheduledThreadPoolExecutor(int corePoolSize,RejectedExecutionHandler handler) {super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,new DelayedWorkQueue(), handler);}在ThreadPoolExecutor談到了獲取隊(duì)列中Runnable對(duì)象即執(zhí)行take方法,看一下DelayedWorkQueue的take()方法,在延時(shí)是調(diào)用了Condition的awaitNanos()方法進(jìn)行延時(shí)執(zhí)行,
private final Condition available = lock.newCondition(); public RunnableScheduledFuture<?> take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {for (;;) {RunnableScheduledFuture<?> first = queue[0];if (first == null)available.await();else {long delay = first.getDelay(NANOSECONDS);if (delay <= 0)return finishPoll(first);first = null; // don't retain ref while waitingif (leader != null)available.await();else {Thread thisThread = Thread.currentThread();leader = thisThread;try {available.awaitNanos(delay);} finally {if (leader == thisThread)leader = null;}}}}} finally {if (leader == null && queue[0] != null)available.signal();lock.unlock();}}周期性執(zhí)行是在執(zhí)行完后會(huì)再次將當(dāng)前任務(wù)放入到線程池中,再次等待延時(shí)執(zhí)行。
//在調(diào)用scheduleAtFixedRate()方法是會(huì)調(diào)用delayedExecute方法將當(dāng)前Runnable對(duì)象添加到隊(duì)列當(dāng)中 //等待執(zhí)行 private void delayedExecute(RunnableScheduledFuture<?> task) {if (isShutdown())reject(task);else {super.getQueue().add(task);if (isShutdown() &&!canRunInCurrentRunState(task.isPeriodic()) &&remove(task))task.cancel(false);elseensurePrestart();}} //在ScheduledFutureTask中,當(dāng)線程池調(diào)用好了Runnable對(duì)象的run方法的時(shí)候,會(huì)調(diào)用reExecutePeriodic()方法將任務(wù)再次放入到線程池中,所以如果在執(zhí)行報(bào)錯(cuò)了,那么就不會(huì)放入到線程池中,/*** Overrides FutureTask version so as to reset/requeue if periodic.*/public void run() {boolean periodic = isPeriodic();if (!canRunInCurrentRunState(periodic))cancel(false);else if (!periodic)ScheduledFutureTask.super.run();else if (ScheduledFutureTask.super.runAndReset()) {setNextRunTime();reExecutePeriodic(outerTask);}}CompletionService
這個(gè)類了解一下就好了,在使用Future并發(fā)執(zhí)行的時(shí)候一般都是將多個(gè)Future對(duì)象用數(shù)組或集合保存起來(lái),然后在循環(huán)數(shù)組或集合調(diào)用get方法獲取結(jié)果集,但是如果使用了CompletionService會(huì)將率先執(zhí)行的結(jié)果集獲取到,就是利用了堵塞隊(duì)列原理實(shí)現(xiàn)的這種效果
用法:
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);CompletionService<String> completionService = new ExecutorCompletionService<String>(newFixedThreadPool);completionService.submit(new Callable<String>() {@Overridepublic String call() throws Exception {return null;}});completionService.take().get();總結(jié)
以上是生活随笔為你收集整理的Java并发编程之线程定时器ScheduledThreadPoolExecutor解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 解决The project descri
- 下一篇: Android初始化本地数据库