Java线程池 - newScheduledThreadPool是如何是实现周期执行的??

9 篇文章 0 订阅
8 篇文章 0 订阅

newScheduledThreadPool是如何是实现周期执行的??

ScheduledThreadPoolExecutor的执行主要分为两个部分。

  1. 当调用scheduleAtFixedRate() 和 scheduleWithFixedDelay() 方法时,会向ScheduledThreadPoolExecutor的DelayedWorkQueue添加一个实现了RunnableScheduledFuture接口的ScheduledFutureTask.
  2. 线程池中的线程从DelayedWorkQueue中获取ScheduledFutrueTask,然后执行。

源码:

//测试 main方法
public statis void main(){
	Executors.newScheduledThreadPool(3).scheduleWithFixedDelay(t, 10,20,TimeUnit.SECONDS);
}

执行scheduleWithFixedDelay方法


  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),
                                          unit.toNanos(-delay));
        RunnableScheduledFuture<Void> t = decorateTask(command, sft);
        sft.outerTask = t;
        delayedExecute(t); // 将任务添加到 DelayedWorkQueue中
        return t;
    }

获取DelayedWorkQueue中的任务

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 waiting
                        if (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();
            }
        }

执行任务

 public void run() {
            boolean periodic = isPeriodic();
            if (!canRunInCurrentRunState(periodic))
                cancel(false);
            else if (!periodic)
                ScheduledFutureTask.super.run();
            else if (ScheduledFutureTask.super.runAndReset()) {
                setNextRunTime(); // 修改time变量为下次将要被执行的时间
                reExecutePeriodic(outerTask);
            }
        }

放回到对列中去

 public boolean offer(Runnable x) {
            if (x == null)
                throw new NullPointerException();
            RunnableScheduledFuture<?> e = (RunnableScheduledFuture<?>)x;
            final ReentrantLock lock = this.lock;
            lock.lock();
            try {
                int i = size;
                if (i >= queue.length)
                    grow();
                size = i + 1;
                if (i == 0) {
                    queue[0] = e;
                    setIndex(e, 0);
                } else {
                    siftUp(i, e);
                }
                if (queue[0] == e) {
                    leader = null;
                    available.signal();
                }
            } finally {
                lock.unlock();
            }
            return true;

具体执行流程

  1. 从DelayedWorkQueue中获取已到期的ScheduleFutureTask(DelayedWorkQueue.task())。
    到期任务是指ScheduleFutureTask的time大于等于当前时间。
  2. 执行ScheduleFutureTask任务
  3. 修改ScheduleFutureTask的time变量为下次将要被执行的时间。
  4. 将修改time之后的ScheduleFutureTask放回DelayedWorkQueue中(DelayedWorkQueue.add())

ScheduledThreadPoolExecutor为了实现周期性的任务执行,对ThreadPoolExecutor做了什么?

1. 使用DelayedWorkQueue作为工作队列
2. 获取任务的方式不同
ScheduledThreadPoolExecutor是通过DelayedWorkQueue.task();获取任务的。
task() 和 poll()的区别,poll和take都是取元素,并且删除头部元素,区别在于poll()是非阻塞的,如果没有到期的元素则
返回null,take()是一直阻塞到返回到期的头部元素。peek():获取但不移除此队列的头部;如果此队列为空,则返回 null。与poll不同,如果队列中没有到期元素可用,则此方法返回下一个将到期的元素(如果存在一个这样的元素)
3. 执行周期任务后,增加了额外的处理,修改time变量,将修改后的任务重新放回DelayedWorkQueue中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值