ScheduledThreadPoolExecutor

java并发编程之美 学习笔记

ScheduledThreadPoolExecutor 是一个可以在指定延时时间后执行或定时执行的任务调度线程池.

ScheduledThreadPoolExecutor

ScheduledFutureTask

ScheduledThreadPoolExecutor 定义了一个重要的类ScheduledFutureTask,首先对它进行分析.
首先看下它的类图。
在这里插入图片描述
它继承自FutureTask同时还实现了RunnableScheduledFuture等接口.

FutureTask
关于FutureTask相关参考:Callable、Future和FutureTask解析

RunnableScheduledFuture接口

public interface RunnableScheduledFuture<V> extends RunnableFuture<V>, ScheduledFuture<V> {

   //是否周期性
    boolean isPeriodic();
}

ScheduledFuture它继承了Delayed, Future接口,自身并没有定义任何方法.


ScheduledFutureTask

public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService {


	//调用ScheduledFutureTask.cancel时,是否从queue中移除
	private volatile boolean removeOnCancel = false;

	//Sequence number
	private static final AtomicLong sequencer = new AtomicLong();

	private class ScheduledFutureTask<V> extends FutureTask<V> implements RunnableScheduledFuture<V> {

		//Sequence number
        private final long sequenceNumber;

       //nanoTime后,执行task
        private long time;

 		
 		/**
 		 * 0: 		说明当前任务是一次性的 ,执行完毕后就退出了 。
 		 * 负数: 	说明当前任务为 fixed-delay 任务,是固定延迟的定时可重复执行任务 。(任务结束时间+period,2period..... n * period)
 		 * 正数:	说明当前任务为 fixed-rate 任务 ,是固定频率的定时可重复执行任务。执行时间为:(time +  -period ,-2period ..... -n*period)
 		 */
        private final long period;

        //由reExecutePeriodic() 重新入队的任务.
        RunnableScheduledFuture<V> outerTask = this;

        //delay queue中的index,用于快速取消
        int heapIndex;

       
        ScheduledFutureTask(Runnable r, V result, long ns) {
            super(r, result);
            this.time = ns;
            this.period = 0;
            this.sequenceNumber = sequencer.getAndIncrement();
        }

        //ScheduledFutureTask()重载构造函数略.....

      

        public long getDelay(TimeUnit unit) {
            return unit.convert(time - now(), NANOSECONDS);
        }

        //按照time 或者getDelay() asc排序;
        public int compareTo(Delayed other) {
          //略..
        }

     	
        public boolean isPeriodic() {
        	// period!=0 表示为周期性任务
            return period != 0;
        }

       //周期性任务,设置下一次执行的时间
        private void setNextRunTime() {
            long p = period;
            if (p > 0)
            	//p>0 ,按照固定频率执行. 执行时间为:time+ (period ,2period ..... n*period)
                time += p;
            else
            	//p<0 , 按照固定延时执行. 执行时间为:执行完成时间+ (period ,2period ..... n*period)
                time = triggerTime(-p);
        }

        public boolean cancel(boolean mayInterruptIfRunning) {
            boolean cancelled = super.cancel(mayInterruptIfRunning);
            if (cancelled && removeOnCancel && heapIndex >= 0)
            	//从workQueue 任务队列中移除task;
                remove(this);
            return cancelled;
        }

        public void run() {
            boolean periodic = isPeriodic();

            if (!canRunInCurrentRunState(periodic))
            	//不允许执行时,取消任务
                cancel(false);
            else if (!periodic)
            	//如果不是周期性任务, 则直接调用super.run();
                ScheduledFutureTask.super.run();
			//ScheduledFutureTask.super.runAndReset() 调用callable.run()执行任务;
			//执行成功后,重新设置state==NEW,然后将任务计算下次执行时间后重新入列
            else if (ScheduledFutureTask.super.runAndReset()) {
            	//设置下一次执行时间;
                setNextRunTime();

                //2.重新入队
                reExecutePeriodic(outerTask);
            }
        }
	}


	
	final long now() {
        return System.nanoTime();
    }

    //1.计算下一次触发事件;
    long triggerTime(long delay) {
        return now() +
            ((delay < (Long.MAX_VALUE >> 1)) ? delay : overflowFree(delay));
    }
	
    //2.
    void reExecutePeriodic(RunnableScheduledFuture<?> task) {
        if (canRunInCurrentRunState(true)) {
        	//重新入队
            super.getQueue().add(task);
            if (!canRunInCurrentRunState(true) && remove(task))
                task.cancel(false);
            else
            	//调用ThreadPoolExecutor方法(),确保至少有一个worker线程.
                ensurePrestart();
        }
    }

}

ScheduledThreadPoolExecutor

构造函数

public class ScheduledThreadPoolExecutor extends ThreadPoolExecutor implements ScheduledExecutorService {
 	public ScheduledThreadPoolExecutor(int corePoolSize,
                                       ThreadFactory threadFactory) {
        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
              new DelayedWorkQueue(), threadFactory);
    }
   //ScheduledThreadPoolExecutor重载构造函数略.....
}

ScheduledThreadPoolExecutor 继承自ThreadPoolExecutor,由构造函数可知它的workQueue是DelayedWorkQueue,


在前面讲解ScheduledFutureTask中有period属性,关于这个属性:

  • 0: 说明当前任务是一次性的 ,执行完毕后就退出了 。
  • 负数: 说明当前任务为 fixed-delay 任务,是固定延迟的定时可重复执行任务
  • 正数: 说明当前任务为 fixed-rate 任务 ,是固定频率的定时可重复执行任务

他们对应如下几种调用方式:

   public ScheduledFuture<?> schedule(Runnable command,
                                       long delay,
                                       TimeUnit unit) {
   }

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

 	public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit) {
 }

schedule(Runnable command,long delay,TimeUnit unit)
该方法的作用是提交一个延迟执行的任务,任务从提交时间算起延迟单位为 unit 的delay 时间 后开始执行 。提交的任务不是周期性任务,任务只会执行一次.

private void delayedExecute(RunnableScheduledFuture<?> task) {
	//判断线程池状态是否为 RUNNING.
    if (isShutdown())
        reject(task);
    else {
    	//添加任务到task
        super.getQueue().add(task);
        if (isShutdown() &&
            !canRunInCurrentRunState(task.isPeriodic()) &&
            remove(task))
            task.cancel(false);
        else
        	//确保至少有一个线程在处理任务.
            ensurePrestart();
    }
}

scheduleAtFixedRate(Runnable command, long initialDelay,long period,TimeUnit unit)

  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();
        ScheduledFutureTask<Void> sft =
            new ScheduledFutureTask<Void>(command,
                                          null,
                                          triggerTime(initialDelay, unit),
                                          //period为负数,表示固定延迟执行...
                                          unit.toNanos(-delay));
        RunnableScheduledFuture<Void> t = decorateTask(command, sft);
        sft.outerTask = t;
        delayedExecute(t);
        return t;
    }

scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)

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();
        ScheduledFutureTask<Void> sft =
            new ScheduledFutureTask<Void>(command,
                                          null,
                                          triggerTime(initialDelay, unit),
                                          //period>0 ,表示固定频率执行任务;
                                          unit.toNanos(period));
        RunnableScheduledFuture<Void> t = decorateTask(command, sft);
        sft.outerTask = t;
        delayedExecute(t);
        return t;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值