关注「Java视界」公众号,获取更多技术干货

实现定时任务的 6 种方式,一网打尽!

实现定时任务有6种方式:

  1. 使用线程创建定时任务
  2. 使用 TimerTask 创建定时任务
  3. 使用线程池创建定时任务
  4. 使用 Quartz 框架实现定时任务
  5. 使用 @Scheduled 注解实现定时任务
  6. xxl-job 实现分布式定时任务

一、使用线程创建定时任务

public class ThreadTask {

    public static class Demo01 {
        static long count = 0;

        public static void main(String[] args) {
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            Thread.sleep(1000);
                            count++;
                            System.out.println(count);
                        } catch (Exception e) {
                            // TODO: handle exception
                        }
                    }
                }
            };
            Thread thread = new Thread(runnable);
            thread.start();
        }
    }
}

在这里插入图片描述

二、使用TimerTask创建定时任务

public class Timer4Task {

    static long count = 0;
    public static void main(String[] args) {
        TimerTask timer4Task = new TimerTask() {
            @Override
            public void run() {
                count++;
                System.out.println(count);
            }
        };
        //创建timer对象设置间隔时间
        Timer timer = new Timer();
        // 间隔天数
        long delay = 0;
        // 间隔毫秒数
        long period = 1000;
        timer.scheduleAtFixedRate(timer4Task, delay, period);
    }
}

在这里插入图片描述

三、使用线程池创建定时任务

public class ThreadPoolTask {
    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // task to run goes here
                System.out.println("Hello !!");
            }
        };
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        // 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
        service.scheduleAtFixedRate(runnable, 1, 1, TimeUnit.SECONDS);
    }
}

在这里插入图片描述

四、使用Quartz框架实现定时任务

Quartz /kwɔːrts/

public class QuartzTask {

    public static void main(String[] args) throws SchedulerException {
        //1.创建Scheduler的工厂
        SchedulerFactory sf = new StdSchedulerFactory();
        //2.从工厂中获取调度器实例
        Scheduler scheduler = sf.getScheduler();
        //3.创建JobDetail,
        JobDetail jb = JobBuilder.newJob(SelfJob.class)
                //job的描述
                .withDescription("this is a ram job")
                //job 的name和group
                .withIdentity("ramJob", "ramGroup")
                .build();
        //任务运行的时间,SimpleSchedle类型触发器有效,3秒后启动任务
        long time = System.currentTimeMillis() + 3 * 1000L;
        Date statTime = new Date(time);
        //4.创建Trigger
        //使用SimpleScheduleBuilder或者CronScheduleBuilder
        Trigger t = TriggerBuilder.newTrigger()
                .withDescription("")
                .withIdentity("ramTrigger", "ramTriggerGroup")
                //.withSchedule(SimpleScheduleBuilder.simpleSchedule())
                //默认当前时间启动
                .startAt(statTime)
                //两秒执行一次,Quartz表达式,支持各种牛逼表达式
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
                .build();
        //5.注册任务和定时器
        scheduler.scheduleJob(jb, t);
        //6.启动 调度器
        scheduler.start();
    }
}
/**
 * 继承Quartz框架中的Job,并重写execute方法
 */
public class SelfJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("quartz Job date:" + System.currentTimeMillis());
    }
}

在这里插入图片描述

五、使用 @Scheduled 注解实现定时任务

@Configuration // 这里使用@Component也行
public class ScheduleTask {

    //添加定时任务-- 50分钟执行一次
    @Scheduled(fixedRate = 50 * 60 * 1000)
    private void updateTask() {
        Console.log("@Scheduled 注解实现定时任务 执行-------------------");
    }
}

启动类增加 @EnableScheduling 注解,启动服务。
在这里插入图片描述

六、使用 xxl-job 实现分布式定时任务

6.1 引入依赖

项目中引入下面的依赖:

 <dependency>
     <groupId>com.xuxueli</groupId>
     <artifactId>xxl-job-core</artifactId>
     <version>2.2.0</version>
 </dependency>       

6.2 配置文件增加配置

xxl:
  job:
    accessToken:
    executor:
      appname: demo
      ip:
      logpath: /data/applogs/xxl-job/jobhandler
      logretentiondays: -1
      port: 9966
    admin:
#      addresses: http://127.0.0.1:8089/xxl-job-admin
      addresses: http://49.234.28.149:8086/xxl-job-admin

6.3 任务接口

@Component
@Slf4j
@RequiredArgsConstructor
public class XxlJobHandler{

    @XxlJob("demoHandler")
    public ReturnT<Object> run (Object s) throws Exception {
        XxlJobLogger.log("xxl-job测试任务开始执行。【args: {}】", s);
        try {
            System.out.println("执行一次xxl-job打印任务!");
            XxlJobLogger.log("xxl-job测试任务执行结束。");
            return null;
        } catch (Exception e) {
            XxlJobLogger.log("xxl-job测试任务执行出错!", e);
            return null;
        }
    }
}

或者这样写也行:

@JobHandler(value="demoHandler")
@Component
public class DemoJobHandler extends IJobHandler {

     static int count;
    @Override
    public ReturnT<String> execute(String param) throws Exception {
        System.out.println("执行job任务"+count++);
        return SUCCESS;
    }
}

6.4 下载并启动 xxl-job

下载地址:https://github.com/xuxueli/xxl-job/

找到 xxl-job-admin 模块,初始化数据库并配置数据库资源、端口等,最后启动服务。

启动后在浏览器输入: http://localhost:8061/xxl-job-admin ,进入 xxl-job 管理后台:
在这里插入图片描述
添加好执行器,再新建一个任务:
在这里插入图片描述
启动服务后会每5秒执行一次,可以根据需求自定义执行时间和周期。
在这里插入图片描述
或者
在这里插入图片描述

七、总结

前5种定时任务方式可以归为一派,原因是这5个方式都是只适用于单实例部署,若是多实例部署那就会重复执行。比如有个定时任务是每天早上8点执行,而你部署了2个实例,那在8点的时候就会执行两遍。
这前5种方式中,使用 @Scheduled 注解最简单,更方便。

xxl-job 的方式,就是在布式集群的情况下,保证定时任务不被重复执行。执行原理同Nginx 类型,所有定时任务通过任务调度平台分发,也可配置负载均衡等。其中的时间表达式可以很灵活,可以自行搜索。

posted @ 2022-06-25 14:02  沙滩de流沙  阅读(2229)  评论(0编辑  收藏  举报

关注「Java视界」公众号,获取更多技术干货