- 浏览: 981536 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
ScheduledThreadPoolExecutor解析一(调度任务,任务队列):http://donald-draper.iteye.com/blog/2367332
前一篇文章我们看了一下调度线程池执行器的调度任务,任务队列,先来回顾一下
ScheduledFutureTask用一个序列号标识延时任务的执行编号,以保证任务的调度按照FIFO的顺序,用time记录任务执行的系统时间,period是任务执行间隔时间,用于计算下一次任务执行系统时间,outerTask为实际的调度任务,heapIndex为任务在队列的索引。调度线程池执行器用DelayedWorkQueue来存储调度任务,DelayedWorkQueue与延时队列DelayedQueue有点像,一个可重入锁控制队列的并发访问,一个available条件控制队列中是否有任务可用,leader为当前正在等待队列头任务可用(队列不为空,队列头任务过期)的线程,当队列不为空或leader被释放,才会触发available条件。DelayedWorkQueue是特为存放ScheduledFutureTask调度任务而定制的。今天来看一下任务的调度,先来看一调度线程池执行器的构造
从调度线程池执行器的构造来看,核心线程池数量是必须设置的,线程工厂和拒绝策略可选,
默认最大线程池数量为 Integer.MAX_VALUE,保活时间为0,即不存在空闲的任务线程,
任务队列为DelayedWorkQueue。
下面我们来看两种任务调度方式scheduleAtFixedRate和scheduleWithFixedDelay;
先看scheduleAtFixedRate
方法中有三个点要关注,为
1.
2.
3.
下面分别来看没一点
1.
这里面要关注的点为计算任务执行的系统时间,这个在前面有说,就不在说了
2.
//简单包装调度任务task
这个方法,子类可以扩展用于管理内部任务,在调度线程池执行器中,仅仅返回调度任务task
3.
//延时执行调度任务
延时方法有两点需要关注:
A.
这里需要关注的就是canRunInCurrentRunState(task.isPeriodic())
B.
//ThreadPoolExecutor
关键在这
//添加一个空任务工作线程
//ThreadPoolExecutor的
addWorker方法中有这么一段:
在工作线程中,执行方法为
再看runWorker
//从队列取任务
从队列取任务,这个就是我们要找到,在延时执行调度任务时,添加任务到延时DelayedWorkQueue,同时添加一个空任务工作线程,空任务工作线程执行时,如果任务为null,则从任务队列中取任务。
再来看ScheduledFutureTask的run方法
//ScheduledFutureTask
自此scheduleAtFixedRate方法,看完我们来小节一下:
首先根据任务command和任务执行系统时间,及任务间隔时间period,构造调度任务
,简单包装调度任务,延时执行调度任务,延时执行调度任务。在延时执行调度任务时,
添加任务到延时DelayedWorkQueue,同时添加一个空任务工作线程,空任务工作线程执行时,
如果任务为null,则从任务队列中取任务。调度任务的执行,如果任务为ScheduledFutureTask,
在运行的时候,从新计算任务下一次执行的系统时间,重置任务线程状态为READY,添加任务到队列。
再看scheduleWithFixedDelay
scheduleWithFixedDelay与scheduleAtFixedRate不同点在构造ScheduledFutureTask时间间隔为-delay
我们先来看
来看ScheduledFutureTask的run方法
再看设置下一次执行的系统时间
计算固定间隔调度任务下一次触发的时间
从上面来看delay为负,那个now() + delay小于当前时间;
再看调度任务ScheduledFutureTask的getDelay
从上面来看getDelay为<0,这个我有点纳闷,getDelay为负的,即在任务队列中延时已经过期,
调度线程池又是如何保证当前任务结束和下一次任务开始的间隔时间为p呢?????我很疑问,如果有网友知道的话,可以在评论里或私信告诉我,感激不尽。
看过scheduleAtFixedRate的执行过程,这两个延时调度任务应该不是什么难题了。
总结:
从调度线程池执行器的构造来看,核心线程池数量是必须设置的,线程工厂和拒绝策略可选,默认最大线程池数量为 Integer.MAX_VALUE,保活时间为0,即不存在空闲的任务线程,
任务队列为DelayedWorkQueue。
scheduleAtFixedRate方法首先根据任务command和任务执行系统时间,
及任务间隔时间period,构造调度任务,简单包装调度任务,延时执行调度任务,
延时执行调度任务。在延时执行调度任务时,
添加任务到延时DelayedWorkQueue,同时添加一个空任务工作线程,空任务工作线程执行时,
如果任务为null,则从任务队列中取任务。调度任务的执行,如果任务为ScheduledFutureTask,
在运行的时候,从新计算任务下一次执行的系统时间,重置任务线程状态为READY,添加任务到队列。
scheduleWithFixedDelay与scheduleAtFixedRate不同点在构造ScheduledFutureTask时间间隔为-delay。时间间隔p为正,以固定的频率调度任务即scheduleAtFixedRate,每隔p时间执行一次任务,无论上一次任务是否执行完,具体任务能否执行,调度线程池无法保证,这要看是否有工作线程可用;当时间间隔p为负,以固定的间隔时间调度任务,即scheduleWithFixedDelay,
当前任务执行完后,等待p时间,再执行下一个任务。
ScheduledThreadPoolExecutor解析三(关闭线程池):
http://donald-draper.iteye.com/blog/2367698
前一篇文章我们看了一下调度线程池执行器的调度任务,任务队列,先来回顾一下
ScheduledFutureTask用一个序列号标识延时任务的执行编号,以保证任务的调度按照FIFO的顺序,用time记录任务执行的系统时间,period是任务执行间隔时间,用于计算下一次任务执行系统时间,outerTask为实际的调度任务,heapIndex为任务在队列的索引。调度线程池执行器用DelayedWorkQueue来存储调度任务,DelayedWorkQueue与延时队列DelayedQueue有点像,一个可重入锁控制队列的并发访问,一个available条件控制队列中是否有任务可用,leader为当前正在等待队列头任务可用(队列不为空,队列头任务过期)的线程,当队列不为空或leader被释放,才会触发available条件。DelayedWorkQueue是特为存放ScheduledFutureTask调度任务而定制的。今天来看一下任务的调度,先来看一调度线程池执行器的构造
/** * Creates a new {@code ScheduledThreadPoolExecutor} with the * given core pool size. * 根据指定的核心线程池数量创建调度线程池执行器,默认最大线程池数量为 Integer.MAX_VALUE, 保活时间为0,即不存在空闲的任务线程,任务队列为DelayedWorkQueue * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @throws IllegalArgumentException if {@code corePoolSize < 0} */ public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue()); } /** * Creates a new {@code ScheduledThreadPoolExecutor} with the * given initial parameters. * 根据指定的核心线程池数量和线程工厂创建调度线程池执行器,默认最大线程池数量为 Integer.MAX_VALUE, 保活时间为0,即不存在空闲的任务线程,任务队列为DelayedWorkQueue * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param threadFactory the factory to use when the executor * creates a new thread * @throws IllegalArgumentException if {@code corePoolSize < 0} * @throws NullPointerException if {@code threadFactory} is null */ public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue(), threadFactory); } /** * Creates a new ScheduledThreadPoolExecutor with the given * initial parameters. * 根据指定的核心线程池数量和拒绝策略创建调度线程池执行器,默认最大线程池数量为 Integer.MAX_VALUE, 保活时间为0,即不存在空闲的任务线程,任务队列为DelayedWorkQueue * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param handler the handler to use when execution is blocked * because the thread bounds and queue capacities are reached * @throws IllegalArgumentException if {@code corePoolSize < 0} * @throws NullPointerException if {@code handler} is null */ public ScheduledThreadPoolExecutor(int corePoolSize, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue(), handler); } /** * Creates a new ScheduledThreadPoolExecutor with the given * initial parameters. * 根据指定的核心线程池数量,线程工厂和拒绝策略创建调度线程池执行器,默认最大线程池数量为 Integer.MAX_VALUE, 保活时间为0,即不存在空闲的任务线程,任务队列为DelayedWorkQueue * @param corePoolSize the number of threads to keep in the pool, even * if they are idle, unless {@code allowCoreThreadTimeOut} is set * @param threadFactory the factory to use when the executor * creates a new thread * @param handler the handler to use when execution is blocked * because the thread bounds and queue capacities are reached * @throws IllegalArgumentException if {@code corePoolSize < 0} * @throws NullPointerException if {@code threadFactory} or * {@code handler} is null */ public ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler); }
从调度线程池执行器的构造来看,核心线程池数量是必须设置的,线程工厂和拒绝策略可选,
默认最大线程池数量为 Integer.MAX_VALUE,保活时间为0,即不存在空闲的任务线程,
任务队列为DelayedWorkQueue。
下面我们来看两种任务调度方式scheduleAtFixedRate和scheduleWithFixedDelay;
先看scheduleAtFixedRate
/** * @throws RejectedExecutionException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) { if (command == null || unit == null) throw new NullPointerException(); if (period <= 0) throw new IllegalArgumentException(); //根据任务command和任务执行系统时间triggerTime(initialDelay, unit), //及任务间隔时间period,构造调度任务 ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(period)); //简单包装调度任务task RunnableScheduledFuture<Void> t = decorateTask(command, sft); //将包装后的实际入队列的调度任务,设为调度任务的outerTask sft.outerTask = t; //延时执行调度任务 delayedExecute(t); return t; }
方法中有三个点要关注,为
1.
//根据任务command和任务执行系统时间triggerTime(initialDelay, unit), //及任务间隔时间period,构造调度任务 ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(period));
2.
//简单包装调度任务task RunnableScheduledFuture<Void> t = decorateTask(command, sft);
3.
//延时执行调度任务 delayedExecute(t);
下面分别来看没一点
1.
//根据任务command和任务执行系统时间triggerTime(initialDelay, unit), //及任务间隔时间period,构造调度任务 ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(period));
这里面要关注的点为计算任务执行的系统时间,这个在前面有说,就不在说了
/** * Returns the trigger time of a delayed action. */ private long triggerTime(long delay, TimeUnit unit) { return triggerTime(unit.toNanos((delay < 0) ? 0 : delay)); } /** * Returns the trigger time of a delayed action. */ long triggerTime(long delay) { return now() + ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay)); }
2.
//简单包装调度任务task
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
/** * Modifies or replaces the task used to execute a runnable. * This method can be used to override the concrete * class used for managing internal tasks. * The default implementation simply returns the given task. * 修改或用于个runnable替代调度任务。这个方法可以简单的重写,用于管理 内部任务。此方仅简单的返回task。 * @param runnable the submitted Runnable * @param task the task created to execute the runnable * @return a task that can execute the runnable * @since 1.6 */ protected <V> RunnableScheduledFuture<V> decorateTask( Runnable runnable, RunnableScheduledFuture<V> task) { return task; }
这个方法,子类可以扩展用于管理内部任务,在调度线程池执行器中,仅仅返回调度任务task
3.
//延时执行调度任务
delayedExecute(t); /** * Main execution method for delayed or periodic tasks. If pool * is shut down, rejects the task. Otherwise adds task to queue * and starts a thread, if necessary, to run it. (We cannot * prestart the thread to run the task because the task (probably) * shouldn't be run yet,) If the pool is shut down while the task * is being added, cancel and remove it if required by state and * run-after-shutdown parameters. * * @param task the task */ private void delayedExecute(RunnableScheduledFuture<?> task) { if (isShutdown()) //如果线程池关闭,则拒绝任务 reject(task); else { //将任务添加到任务队列 super.getQueue().add(task); if (isShutdown() && !canRunInCurrentRunState(task.isPeriodic()) && remove(task)) //如果线程池关闭,且可以执行间歇性任务,从队列移除任务, //继续以不可中断方式执行正在执行的调度任务 task.cancel(false); else //添加一个空闲工作线程, ensurePrestart(); } }
延时方法有两点需要关注:
A.
if (isShutdown() && !canRunInCurrentRunState(task.isPeriodic()) && remove(task)) //如果线程池关闭,且可以执行间歇性任务,从队列移除任务, //继续以不可中断方式执行正在执行的调度任务 task.cancel(false);
这里需要关注的就是canRunInCurrentRunState(task.isPeriodic())
/** * Returns true if can run a task given current run state * and run-after-shutdown parameters. * 此方法的目的是,判断是否可以,在线程池关闭的状态下,继续执行任务; continueExistingPeriodicTasksAfterShutdown用于间歇性任务(true,可以继续执行正在执行的调度任务), executeExistingDelayedTasksAfterShutdown用于延时任务(true,可以继续执行正在执行的延时任务) * @param periodic true if this task periodic, false if delayed */ boolean canRunInCurrentRunState(boolean periodic) { return isRunningOrShutdown(periodic ? continueExistingPeriodicTasksAfterShutdown : executeExistingDelayedTasksAfterShutdown); }
B.
else //添加一个空任务工作线程, ensurePrestart();
//ThreadPoolExecutor
//添加一个空任务工作线程 /** * Same as prestartCoreThread except arranges that at least one * thread is started even if corePoolSize is 0. */ void ensurePrestart() { int wc = workerCountOf(ctl.get()); if (wc < corePoolSize) //添加一个空任务工作线程 addWorker(null, true); else if (wc == 0) addWorker(null, false); }
关键在这
//添加一个空任务工作线程
addWorker(null, true);
//ThreadPoolExecutor的
addWorker方法中有这么一段:
private boolean addWorker(Runnable firstTask, boolean core) { ... if (workerAdded) { t.start();//执行工作线程 workerStarted = true; } ... }
在工作线程中,执行方法为
private final class Worker extends AbstractQueuedSynchronizer implements Runnable { ... /** Delegates main run loop to outer runWorker */ public void run() { runWorker(this); } ... }
再看runWorker
final void runWorker(Worker w) { //如果工作线程的任务为空,则从任务队列取任务 while (task != null || (task = getTask()) != null) { ... try { task.run(); } ... }
//从队列取任务
private Runnable getTask() { try { Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); } }
从队列取任务,这个就是我们要找到,在延时执行调度任务时,添加任务到延时DelayedWorkQueue,同时添加一个空任务工作线程,空任务工作线程执行时,如果任务为null,则从任务队列中取任务。
再来看ScheduledFutureTask的run方法
//ScheduledFutureTask
/** * 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(); //如果任务为ScheduledFutureTask,则重置任务线程状态为READY else if (ScheduledFutureTask.super.runAndReset()) { //设置下一次执行的系统时间 setNextRunTime(); //任务重新入队列 reExecutePeriodic(outerTask); } } /** * Requeues a periodic task unless current run state precludes it. * Same idea as delayedExecute except drops task rather than rejecting. * * @param task the task */ void reExecutePeriodic(RunnableScheduledFuture<?> task) { if (canRunInCurrentRunState(true)) { //重新添加任务到队列 super.getQueue().add(task); if (!canRunInCurrentRunState(true) && remove(task)) task.cancel(false); else ensurePrestart(); } }
自此scheduleAtFixedRate方法,看完我们来小节一下:
首先根据任务command和任务执行系统时间,及任务间隔时间period,构造调度任务
,简单包装调度任务,延时执行调度任务,延时执行调度任务。在延时执行调度任务时,
添加任务到延时DelayedWorkQueue,同时添加一个空任务工作线程,空任务工作线程执行时,
如果任务为null,则从任务队列中取任务。调度任务的执行,如果任务为ScheduledFutureTask,
在运行的时候,从新计算任务下一次执行的系统时间,重置任务线程状态为READY,添加任务到队列。
再看scheduleWithFixedDelay
/** * @throws RejectedExecutionException {@inheritDoc} * @throws NullPointerException {@inheritDoc} * @throws IllegalArgumentException {@inheritDoc} */ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) { if (command == null || unit == null) throw new NullPointerException(); if (delay <= 0) throw new IllegalArgumentException(); //任务command和任务执行系统时间,及任务间隔时间period,构造调度任务 ScheduledFutureTask<Void> sft = new ScheduledFutureTask<Void>(command, null, triggerTime(initialDelay, unit), unit.toNanos(-delay)); //包装任务 RunnableScheduledFuture<Void> t = decorateTask(command, sft); sft.outerTask = t; //延时执行 delayedExecute(t); return t; }
scheduleWithFixedDelay与scheduleAtFixedRate不同点在构造ScheduledFutureTask时间间隔为-delay
我们先来看
unit.toNanos(-delay)
public enum TimeUnit { NANOSECONDS { public long toNanos(long d) { return d; } public long toMicros(long d) { return d/(C1/C0); } public long toMillis(long d) { return d/(C2/C0); } public long toSeconds(long d) { return d/(C3/C0); } public long toMinutes(long d) { return d/(C4/C0); } public long toHours(long d) { return d/(C5/C0); } public long toDays(long d) { return d/(C6/C0); } public long convert(long d, TimeUnit u) { return u.toNanos(d); } int excessNanos(long d, long m) { return (int)(d - (m*C2)); } },MICROSECONDS{...},MILLISECONDS{...},...
来看ScheduledFutureTask的run方法
//ScheduledFutureTask /** * 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(); //如果任务为ScheduledFutureTask,则重置任务线程状态为READY else if (ScheduledFutureTask.super.runAndReset()) { //设置下一次执行的系统时间 setNextRunTime(); //任务重新入队列 reExecutePeriodic(outerTask); } }
再看设置下一次执行的系统时间
/** * Sets the next time to run for a periodic task. 设置间歇性调度任务下一次执行的时间 */ private void setNextRunTime() { long p = period; //以固定的频率调度任务即scheduleAtFixedRate, //每隔p时间执行一次任务无论,上一次任务是否执行完 if (p > 0) time += p; else //以固定的间隔时间调度任务,即scheduleWithFixedDelay, //当前任务执行完后,等待p时间,再执行下一个任务 time = triggerTime(-p); }
计算固定间隔调度任务下一次触发的时间
/** * Returns the trigger time of a delayed action. */ long triggerTime(long delay) { return now() + ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay)); }
从上面来看delay为负,那个now() + delay小于当前时间;
再看调度任务ScheduledFutureTask的getDelay
public long getDelay(TimeUnit unit) { //调度系统时间-当前系统时间 return unit.convert(time - now(), TimeUnit.NANOSECONDS); }
从上面来看getDelay为<0,这个我有点纳闷,getDelay为负的,即在任务队列中延时已经过期,
调度线程池又是如何保证当前任务结束和下一次任务开始的间隔时间为p呢?????我很疑问,如果有网友知道的话,可以在评论里或私信告诉我,感激不尽。
//调度一个延时的Runnable任务 /** * @throws RejectedExecutionException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) { if (command == null || unit == null) throw new NullPointerException(); RunnableScheduledFuture<?> t = decorateTask(command, new ScheduledFutureTask<Void>(command, null, triggerTime(delay, unit))); delayedExecute(t); return t; } //调度一个延时的Callable任务 /** * @throws RejectedExecutionException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) { if (callable == null || unit == null) throw new NullPointerException(); RunnableScheduledFuture<V> t = decorateTask(callable, new ScheduledFutureTask<V>(callable, triggerTime(delay, unit))); delayedExecute(t); return t; }
看过scheduleAtFixedRate的执行过程,这两个延时调度任务应该不是什么难题了。
总结:
从调度线程池执行器的构造来看,核心线程池数量是必须设置的,线程工厂和拒绝策略可选,默认最大线程池数量为 Integer.MAX_VALUE,保活时间为0,即不存在空闲的任务线程,
任务队列为DelayedWorkQueue。
scheduleAtFixedRate方法首先根据任务command和任务执行系统时间,
及任务间隔时间period,构造调度任务,简单包装调度任务,延时执行调度任务,
延时执行调度任务。在延时执行调度任务时,
添加任务到延时DelayedWorkQueue,同时添加一个空任务工作线程,空任务工作线程执行时,
如果任务为null,则从任务队列中取任务。调度任务的执行,如果任务为ScheduledFutureTask,
在运行的时候,从新计算任务下一次执行的系统时间,重置任务线程状态为READY,添加任务到队列。
scheduleWithFixedDelay与scheduleAtFixedRate不同点在构造ScheduledFutureTask时间间隔为-delay。时间间隔p为正,以固定的频率调度任务即scheduleAtFixedRate,每隔p时间执行一次任务,无论上一次任务是否执行完,具体任务能否执行,调度线程池无法保证,这要看是否有工作线程可用;当时间间隔p为负,以固定的间隔时间调度任务,即scheduleWithFixedDelay,
当前任务执行完后,等待p时间,再执行下一个任务。
ScheduledThreadPoolExecutor解析三(关闭线程池):
http://donald-draper.iteye.com/blog/2367698
发表评论
-
Executors解析
2017-04-07 14:38 1247ThreadPoolExecutor解析一(核心线程池数量、线 ... -
ScheduledThreadPoolExecutor解析三(关闭线程池)
2017-04-06 20:52 4451ScheduledThreadPoolExecutor解析一( ... -
ScheduledThreadPoolExecutor解析一(调度任务,任务队列)
2017-04-04 22:59 4988Executor接口的定义:http://donald-dra ... -
ThreadPoolExecutor解析四(线程池关闭)
2017-04-03 23:02 9101Executor接口的定义:http: ... -
ThreadPoolExecutor解析三(线程池执行提交任务)
2017-04-03 12:06 6082Executor接口的定义:http://donald-dra ... -
ThreadPoolExecutor解析二(线程工厂、工作线程,拒绝策略等)
2017-04-01 17:12 3037Executor接口的定义:http://donald-dra ... -
ThreadPoolExecutor解析一(核心线程池数量、线程池状态等)
2017-03-31 22:01 20515Executor接口的定义:http://donald-dra ... -
ScheduledExecutorService接口定义
2017-03-29 12:53 1504Executor接口的定义:http://donald-dra ... -
AbstractExecutorService解析
2017-03-29 08:27 1073Executor接口的定义:http: ... -
ExecutorCompletionService解析
2017-03-28 14:27 1586Executor接口的定义:http://donald-dra ... -
CompletionService接口定义
2017-03-28 12:39 1062Executor接口的定义:http://donald-dra ... -
FutureTask解析
2017-03-27 12:59 1326package java.util.concurrent; ... -
Future接口定义
2017-03-26 09:40 1193/* * Written by Doug Lea with ... -
ExecutorService接口定义
2017-03-25 22:14 1159Executor接口的定义:http://donald-dra ... -
Executor接口的定义
2017-03-24 23:24 1672package java.util.concurrent; ... -
简单测试线程池拒绝执行任务策略
2017-03-24 22:37 2025线程池多余任务的拒绝执行策略有四中,分别是直接丢弃任务Disc ... -
JAVA集合类简单综述
2017-03-23 22:51 921Queue接口定义:http://donald-draper. ... -
DelayQueue解析
2017-03-23 11:00 1735Queue接口定义:http://donald-draper. ... -
SynchronousQueue解析下-TransferQueue
2017-03-22 22:20 2134Queue接口定义:http://donald-draper. ... -
SynchronousQueue解析上-TransferStack
2017-03-21 22:08 3049Queue接口定义:http://donald-draper. ...
相关推荐
本篇将深入解析Java定时任务的原理、常见实现方式以及应用场景,并对它的优缺点进行分析。 一、Java定时任务简介 Java定时任务是一种编程机制,能够帮助开发者实现按需执行的任务,这些任务可能是周期性的或一次性...
此外,Spring还提供了`TaskScheduler`和`ThreadPoolTaskScheduler`接口,以及`@Async`注解进行异步任务调度。 5. **Cron表达式** Cron表达式是一种广泛使用的用于定义周期性任务的时间格式,它由6或7个字段组成,...
线程池的执行过程主要包括任务提交、任务调度和线程执行。当调用 `ExecutorService.execute()` 时,任务会被添加到工作队列。如果线程池未满,新线程会立即启动执行任务;如果已满,则任务会在队列中等待,直到有...
`ScheduledThreadPoolExecutor`实现了这个接口,提供了更强大、更灵活的定时任务管理能力,支持多线程并发执行,同时处理中断和异常更为完善。 总结,`Timer`类是Java中基础的定时任务工具,适用于简单的定时需求。...
4. **定时线程池**:可以定时或周期性执行任务,适合定时任务调度。 在实际应用中,理解线程池的源码有助于我们更好地定制线程池,优化系统性能。例如,通过自定义拒绝策略(RejectedExecutionHandler)来处理任务...
它允许设置延迟执行或定期执行任务,如ScheduledThreadPoolExecutor,可以创建一个定时任务池,用于执行周期性的任务调度。 **5. CompletableFuture** Java 8引入的CompletableFuture类为异步编程提供了强大的工具...
- **Executor框架**:是Java并发API的核心组件之一,它提供了一种灵活的方式来管理线程池,支持异步任务执行、任务调度等功能。 - **Future与Callable**:`Future`接口表示异步计算的结果,而`Callable`是一个定义了...
Java的`ScheduledExecutorService`或`ScheduledThreadPoolExecutor`可以替代`Timer`类,提供更高级的定时任务管理。这些类支持定时和周期性的任务执行,且具有更好的线程池管理和取消任务的功能。 4. **数据持久化*...
这使得我们可以使用Java并发库中的其他执行器,如`ScheduledThreadPoolExecutor`来实现定时任务或者周期性任务。 另外,`ThreadPoolTaskScheduler`是Spring提供的一个调度任务执行器,它可以用来执行定时任务。配置...
4. **ScheduledThreadPoolExecutor**:与前三个不同,它可以定时或周期性执行任务,适用于需要定期调度的任务,如定时任务、延迟执行等。 三、线程池核心参数 1. **corePoolSize**:线程池的基本大小,即当线程池...
- `ScheduledExecutorService`:Java并发包中的高级任务调度工具,提供更灵活的定时任务处理,如`ScheduledThreadPoolExecutor`。 4. **事件驱动编程**: - Java Swing或JavaFX:如果"ControlHorarios"涉及图形...
- `ScheduledThreadPoolExecutor`:支持定时及周期性任务执行。 #### 2. 原子类 Java并发包`java.util.concurrent.atomic`提供了几个原子类来支持无锁编程: - `AtomicInteger`、`AtomicLong`等:提供了基本类型的...
这些内部类实现了ExecutorService接口,提供了调度和执行任务的能力。例如,`newFixedThreadPool`方法创建`ThreadPoolExecutor`实例时,传入了核心线程数、线程工厂和拒绝策略等参数,确保线程池的行为符合预期。 ...
最后,书中的实战部分可能包含解决实际问题的案例,如高并发场景下的任务调度、异步处理、线程安全问题排查等。这些实战经验有助于读者将理论知识转化为实际技能。 总之,《多线程编程实战指南-核心篇》是一本全面...
《深入解析"Tik Tak To":Java编程中的计时器应用》 ...通过理解并实践`tik_tak_to`项目中的计时器设计,开发者可以提升自己在Java并发编程和任务调度方面的技能,这对于构建高效、稳定的后台服务至关重要。
源代码中可能会包含使用这些新工具进行并发任务调度和执行的示例。 2. **Swing增强**:JDK6对Swing进行了优化,比如添加了`JSplitPane`的动态调整功能,增强了`JTable`的性能。源代码可能包含使用这些新功能构建...
- **ScheduledThreadPoolExecutor**:扩展了`ThreadPoolExecutor`,提供了定时调度任务的能力。 ##### java.io包 - 包含了大量的输入/输出流类,用于处理文件和其他资源的数据读写。 ##### java.math包 - **...
9. **线程模型**:Netty的EventLoop和EventLoopGroup是其异步模型的核心,它们负责处理I/O事件,调度任务。在RPC框架中,合理的线程模型设计对于性能和响应速度至关重要。 通过以上组件和概念的组合,基于Netty4的...