任务调度(定时任务)

任务调度
任务调度,简单来说就是定时任务,是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务。

Java常见的任务调度方式
基于JDK方式:TimerScheduledExecutorService
Time (java.util.Timer) JDK 自带,简单单一,复杂场景不适用。

public class TimeTaskDemo {
    static long count = 0;
    public static void main(String[] args) {
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                count++;
                System.out.println("TIME TASK ===>" + count);
            }
        };
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(timerTask, 0, 1000);
    }
}

ScheduledExecutorService (线程池)JKD 自带,基于线程池实现,可搭配异步(@Asnyc)。

@RestController
public class ScheduledExecutorDemoContoller {
    //... 省略其他代码
    @GetMapping("/testSES")
    public String ScheduledExecutorService() {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("ScheduledExecutorService定时任务执行:" + new Date());                
            }
        }, 1, 1, TimeUnit.SECONDS);
        System.out.println("ScheduledExecutorService 定时任务启动:" + new Date());
        // 可同时设定多个任务只需再次service.scheduleAtFixedRate(...)...即可
        return "ScheduledExecutorService OK";        
    }
}

其他框架

  • Spring Task (基于注解@Scheduled) Spring 提供,支持注解和配置文件形式,支持 Cron表达式,使用简单且功能强大。
@Component
@EnableScheduling //开启定时任务
public class ScheduleTaskDemo {
    @Scheduled(cron = "0/5 * * * * ?")
    private void configureTasks() {
        System.out.println("test info ===>" + LocalDateTime.now());
    }
}
  • Quartz 功能强大,可实现较复杂调度功能,支持分布式调度,但配置稍复杂。
// Maven依赖
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.2.1</version>
</dependency>
<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.2.1</version>
</dependency>
// 任务调度类,execute 被定时执行某某操作的具体方法
@Component
public class TimeJob implements Job {
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("quartz job date:" + new Date().getTime());
    }
}
@RestController
public class TestQuatrtzController {
    // 省略其他代码...
    @GetMapping("/quartz")
    public String testQuartz(){
    SchedulerFactory sf = new StdSchedulerFactory();
      Scheduler scheduler = sf.getScheduler();
      JobDetail job = JobBuilder.newJob(TimeJob .class)
              .withDescription("This is darian job ,welcome you come here ...") 
              .withIdentity("darianJob", "darianGroup")
              .build();
      long time =  System.currentTimeMillis() + 3*1000L; //3秒后启动任务
      Date startTime = new Date(time);
      //使用SimpleScheduleBuilder或者CronScheduleBuilder
      Trigger trigger = TriggerBuilder.newTrigger()
                  .withDescription("")
                  .withIdentity("darianTrigger", "darianTriggerGroup")
                  //.withSchedule(SimpleScheduleBuilder.simpleSchedule())
                  .startAt(startTime)
                  .withSchedule(CronScheduleBuilder.cronSchedule("0/3 * * * * ? *")) 
                  .build();
                  
      scheduler.scheduleJob(job, trigger);
      scheduler.start();
        return "OK!";
    }
}

Corn(Quartz)表达式在线生成:http://cron.qqe2.com/

任务调度的问题

上面我们讲了几种传统给任务调度(定时任务),缺点也很明显,不支持高并发、资源没有最大化利用、没有容错、不方便管理等等。

分布式情况下定时任务的调度会出现那些问题?
最大的问题即:任务调度的幂等性问题,简单来说就是不能被重复执行,所以我们需要一个分布式任务调度平台,可以为我们提供管理、高可用、集群、报警等机制的平台。

分布式任务调度平台

这里介绍的分布式任务调度平台指的是XXL-JOB ,XXL-JOB 是分布式定时任务的解决方案之一。XXL-JOB 功能非常的齐全、上手简单易懂,优点非常多,点击了解 xxl-job

XXL-JOB 采用的概念是:“调度中心” 和 “执行器”。

调度中心:你可以想象成注册中心,所有的任务都需要经过它
执行器:具体的任务执行者

在官网有相应的开发文档,想要使用XXL-JOB ,首先需要前往XXL-JOB GitHub地址:https://github.com/xuxueli/xxl-job 下载相应的压缩包。

快速入门XXL-JOB → xxl-job中文文档

注意: 我在使用XXL-JOB 2.1.2 版本时,环境要求 Mysql 5.7,我使用的是 Mysql 5.6,在执行 XXL-JOB 的 “调度数据库初始化SQL” 时,某张表出错如下:
“ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes”
这个错误,是指超出索引字节的限制,并不是指字段长度限制。在官方文档“Limits on InnoDB Tables”有关于这方面的介绍、描述(详情请见参考Mysql5.6官方文档)。

解决方案:
方案1:首先需要对Mysql做一些调整,然后在执行的SQL添加特定参数。
方案2:升级MySQL至5.7

下面讲的是方案1:

我用的Mysql的自带工具连接操作Msql,你用其他的MySQL可视化工具连接执行也可以。

 

在执行创建表出错为:ERROR 1071 : Specified key was too long; max key length is 767 bytes 的SQL后面添加相应参数,如下图。

 

 

 


posted @ 2021-09-06 11:17  嗨,小yu  阅读(372)  评论(0)    收藏  举报