Java ScheduledExecutorService 使用学习

        Java 中的 ScheduledExecutorService 接口用来实现延迟执行或者定时执行的任务。在阅读 RocketMQ 源码(release-4.7.1版本)的过程中,发现很多地方都是使用的 ScheduledExecutorService 来实现定时任务。比如,在 broker 启动过程,BrokerController 类中使用 scheduledExecutorService 执行 broker 启动后的定时任务,比如消息消费偏移量 offset 的持久化定时任务,大致如下:

package org.apache.rocketmq.broker;

public class BrokerController {
    
     /**
      * 这里省略一些字段
      */    

     
     /**
      * 使用 Executors.newSingleThreadScheduledExecutor 创建单线程的定时调度任务线程池
      */  
     private final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl(
        "BrokerControllerScheduledThread"));


     /**
      * broker 启动的初始化方法
      */
     public boolean initialize() throws CloneNotSupportedException {
         // 省略部分代码
         
         this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    try {
                        BrokerController.this.getBrokerStats().record();
                    } catch (Throwable e) {
                        log.error("schedule record error.", e);
                    }
                }
            }, initialDelay, period, TimeUnit.MILLISECONDS);

            // broker 启动10s后,默认每隔5s钟持久化一次消费消息偏移量offset信息
            this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    try {
                        // 持久化消费偏移量,将 ConsumerOffsetManager 序列化为json文件保存在本地
                        BrokerController.this.consumerOffsetManager.persist();
                    } catch (Throwable e) {
                        log.error("schedule persist consumerOffset error.", e);
                    }
                }
            }, 1000 * 10, this.brokerConfig.getFlushConsumerOffsetInterval(), TimeUnit.MILLISECONDS);

            this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
                @Override
                public void run() {
                    try {
                        BrokerController.this.consumerFilterManager.persist();
                    } catch (Throwable e) {
                        log.error("schedule persist consumer filter error.", e);
                    }
                }
            }, 1000 * 10, 1000 * 10, TimeUnit.MILLISECONDS);

           
           // 后面还有很多.......
     
     }

}

所以觉得有必要学习理解 ScheduledExecutorService。大致看了一下 ScheduledExecutorService 实现类 ScheduledThreadPoolExecutor 的代码,跟我们常用的 ThreadPoolExecutor 线程池类还是有一些差异的,里面有一个基于堆实现的优先队列,后面要再深入学习下,本篇先学习 ScheduledExecutorService 的使用,先学会使用,再分析原理。

本文使用JDK版本:JDK8.

一、ScheduledExecutorService 接口定义

首先,ScheduledExecutorService 是一个接口,它实现了 ExecutorService 接口。

在 ScheduledExecutorService 接口中又新定义了下面四个方法:

1、public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);

在指定延迟时间后执行一个 Runnable 任务。因为是 Runnable ,返回值 ScheduledFuture.get() 返回值为 null。

2、 <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);

在指定延迟时间后执行一个 Callable 任务。因为是 Callable ,所以 ScheduledFuture.get() 有返回值。

3、ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);

创建并执行一个在给定初始延迟 (initialDelay) 后首次启动执行的定时任务,任务执行具有给定的周期 (period);
也就是将在 initialDelay 后开始执行,然后在 initialDelay + period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
如果任务的任何一个执行遇到异常,则后续执行都会被取消相反,任务正常执行的话,只能通过线程池的取消或终止操作来终止该任务。

如果此任务的任何一个执行要花费比其周期更长的时间,则后续的执行将会被推迟,不会出现两个任务同时执行。

4、ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);

创建并执行一个在给定初始延迟 (initialDelay) 后首次启动执行的任务,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟(delay)。
如果任务的任一执行遇到异常,就会取消后续任务执行。相反,任务正常执行的话,只能通过线程池的取消或终止操作来终止该任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值