一、定时任务实现的几种方式
1. Timer:线程调度任务以供将来在后台线程中执行的功能。 任务可以安排一次执行,或定期重复执行。Timer是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
API文档:http://www.matools.com/file/manual/jdk_api_1.8_google/index.html?overview-summary.html
2. ScheduledExecutorService:也jdk自带的一个类,位于java.util.concurrent包下;它是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
API文档:http://www.matools.com/file/manual/jdk_api_1.8_google/index.html?overview-summary.html
3. Spring Task:Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。
官方文档:https://spring.io/guides/gs/scheduling-tasks/
4. Quartz:是一个由 Java 编写的开源作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。它允许程序开发人员根据时间的间隔来调度作业,并且实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。官网:http://www.quartz-scheduler.org/
5. 第三方定时任务调度工具,比如:xxl-job(https://gitee.com/xuxueli0323/xxl-job)
二、SpringBoot整合实现几种定时任务
1. 创建SpringBoot项目,引入相关的jar包到pom.xml文件
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.62</version> </dependency>
其他jar包都是自带的,不用导入了
2. 创建的项目结构如下:
3. 代码实现
(1)配置类:
AsyncConfig.java ——异步任务配置类
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; /** * @ClassName: AsyncConfig * @Author: liuhefei * @Description: 定义一个支持异步任务的配置类 * @Date: 2019/10/31 18:53 */ @Configuration //表明该类是一个配置类 @EnableAsync //开启异步事件的支持 public class AsyncConfig { /* *此处成员变量应该使用@Value从配置中读取 */ private int corePoolSize = 10; private int maxPoolSize = 200; private int queueCapacity = 10; @Bean public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.initialize(); return executor; } }
QuartzConfig.java——Quartz调度任务配置类
import com.lhf.springboot.quartz.QuartzTest; import com.lhf.springboot.quartz.QuartzTest1; import org.quartz.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @ClassName: QuartzConfig * @Author: liuhefei * @Description: Quartz定时任务配置类 * @Date: 2019/10/31 19:06 */ @Configuration public class QuartzConfig { @Bean public JobDetail quartzDetail(){ return JobBuilder.newJob(QuartzTest.class).withIdentity("quartzTest").storeDurably().build(); } @Bean public Trigger quartzTrigger(){ SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(15) //设置时间周期单位秒 .repeatForever(); return TriggerBuilder.newTrigger().forJob(quartzDetail()) .withIdentity("quartzTestJob") .withSchedule(scheduleBuilder) .build(); } /*****************************************************************************************************************/ @Bean public JobDetail interviewPlansJobDetail(){ return JobBuilder.newJob(QuartzTest1.class)//PrintTimeJob我们的业务类 .withIdentity("quartzTest1")//可以给该JobDetail起一个id //每个JobDetail内都有一个Map,包含了关联到这个Job的数据,在Job类中可以通过context获取 .usingJobData("msg1", "quartzTest1")//关联键值对 .storeDurably()//即使没有Trigger关联时,也不需要删除该JobDetail .build(); } @Bean public Trigger interviewPlansJobTrigger() { CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0 0/3 * * * ? "); // 0 0 0/1 * * ? return TriggerBuilder.newTrigger() .forJob(interviewPlansJobDetail())//关联上述的JobDetail .withIdentity("quartzTestJob1")//给Trigger起个名字 .withSchedule(cronScheduleBuilder) .build(); } }
(2)quartz实现定时任务
QuartzTest.java——quartz定时任务1
import com.lhf.springboot.util.RandomUtils; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; /** * @ClassName: QuartzTest * @Author: liuhefei * @Description: Quartz定时任务 * @Date: 2019/10/31 19:08 */ public class QuartzTest extends QuartzJobBean { //执行定时任务 @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("quartz定时任务1: " + RandomUtils.getRandomString()); } }
QuartzTest1.java——quartz定时任务2
import com.lhf.springboot.util.RandomUtils; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; /** * @ClassName: QuartzTest1 * @Author: liuhefei * @Description: Quartz定时任务 * @Date: 2019/10/31 19:17 */ public class QuartzTest1 extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { System.out.println("quartz定时任务2: " + RandomUtils.getRandomNum(4) + "-->" + RandomUtils.getRandomString()); } }
(3)ScheduledExecutorService实现定时任务
ScheduledExecutorServiceDemo.java
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.Date; /** * @ClassName: ScheduledExecutorServiceDemo * @Author: liuhefei * @Description: ScheduledExecutorService实现定时任务 * @Date: 2019/10/31 18:22 */ public class ScheduledExecutorServiceDemo { public void scheduledJob(){ ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); //参数:1.任务名称 2. 首次执行的延时时间 3. 任务执行间隔 4. 间隔时间单位 service.scheduleAtFixedRate(()->System.out.println("ScheduledExecutorService Job : " + new Date()), 0, 4, TimeUnit.SECONDS); } }
(4)Spring Task实现定时任务
AsyncTask.java——开启异步任务
import com.lhf.springboot.util.RandomUtils; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** * @ClassName: AsyncTask * @Author: liuhefei * @Description: TODD * @Date: 2019/10/31 18:57 */ @Async //开启异步任务类,类中的每个方法都是定时任务,该注解可以加到类和方法上 @Component public class AsyncTask { //@Async @Scheduled(cron = "0/7 * * * * * ") public void task1(){ System.out.println("异步任务1: " + System.currentTimeMillis()); } //@Async @Scheduled(cron = "0/9 * * * * * ") public void task2(){ System.out.println("异步任务2:" + RandomUtils.getRandomString()); } }
SpringTaskDemo.java
import com.lhf.springboot.util.RandomUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.util.Date; /** * @ClassName: SpringTaskDemo * @Author: liuhefei * @Description: Spring Task实现定时任务 * @Date: 2019/10/31 18:31 */ @Component public class SpringTaskDemo { private final Logger logger = LoggerFactory.getLogger(SpringTaskDemo.class); @Scheduled(cron = "0/5 * * * * * ") public void scheduledCron(){ logger.info("===>>使用cron表达式实现定时任务:" + System.currentTimeMillis()); } @Scheduled(fixedRate = 6000) public void scheduledFixedRate(){ logger.info("===>>使用fixedRate实现定时任务: " + RandomUtils.getRandomString(8)); } @Scheduled(fixedDelay = 7000) public void scheduledFixedDelay(){ logger.info("===>>使用fixedDelay实现定时任务: " + new Date() + " -- " + RandomUtils.getRandomString(4)); } }
(5)Timer实现定时任务
TimerDemo.java
import com.lhf.springboot.util.RandomUtils; import java.util.Timer; import java.util.TimerTask; /** * @ClassName: TimerDemo * @Author: liuhefei * @Description: Timer定时任务 * @Date: 2019/10/31 17:58 */ public class TimerDemo { public void timerJob(){ TimerTask timerTask = new TimerTask() { @Override public void run() { System.out.println("Timer Job: " + RandomUtils.getRandomString()); } }; Timer timer = new Timer(); //每3秒执行一次 timer.schedule(timerTask, 10, 3000); } }
(6)工具类
RandomUtils.java——随机生成字符串工具类
import java.util.Random; /** * @ClassName: RandomUtils * @Desc: 生成随机字符串 * @Author: liuhefei * @Date: 2019/2/28 14:16 */ public class RandomUtils { public static String getRandomString(int length){ //1. 定义一个字符串(A-Z,a-z,0-9)即62个数字字母; //String str="zxcvbnmlkjhgfdsaqwertyuiopQWERTYUIOPASDFGHJKLZXCVBNM1234567890"; String str="用我三生烟火,换你一世迷离。长街长,烟花繁,你挑灯回看,短亭短,红尘辗,我把萧再叹。终是谁使弦断,花落肩头,恍惚迷离多少红颜悴,多少相思碎,唯留血染墨香哭乱冢。苍茫大地一剑尽挽破,何处繁华笙歌落。斜倚云端千壶掩寂寞,纵使他人空笑我。任他凡事清浊,为你一笑间轮回甘堕。寄君一曲,不问曲终人聚散。谁将烟焚散,散了纵横的牵绊。听弦断,断那三千痴缠。坠花湮,湮没一朝风涟。花若怜,落在谁的指尖。灯火星星,人声杳杳,歌不尽乱世烽火。如花美眷,似水流年,回得了过去,回不了当初。似此星辰非昨夜,为谁风露立中宵。蝴蝶很美,终究蝴蝶飞不过沧海。山河拱手,为君一笑 。待浮花浪蕊俱尽,伴君幽独。"; //2. 由Random生成随机数 Random random=new Random(); StringBuffer sb=new StringBuffer(); //3. 长度为几就循环几次 for(int i=0; i<length; ++i){ //从62个的数字或字母中选择 int number=random.nextInt(62); //将产生的数字通过length次承载到sb中 sb.append(str.charAt(number)); } //将承载的字符转换成字符串 return sb.toString(); } public static String getRandomString(){ String[] strArr= {"乾坤有序,宇宙无疆,星辰密布,斗柄指航。", "昼白夜黑,日明月亮,风驰雪舞,电闪雷响。", "云腾致雨,露结晨霜,虹霓霞辉,雾沉雹降。", "春生夏长,秋收冬藏,时令应候,寒来暑往。", "远古洪荒,海田沧桑,陆地漂移,板块碰撞。", "山岳巍峨,湖泊荡漾,植被旷野,岛撒汪洋。", "冰川冻土,沙漠沃壤,木丰树森,岩多滩广。", "鸟飞兽走,鳞潜羽翔,境态和谐,物种安详。", "形分上下,道合阴阳,幽冥杳渺,天体著彰。", "凝气为精,聚能以场,缩浓而质,积微显量。", "化巨幻虚,恍惚成象,强固凌弱,柔亦制刚。", "终极必反,存兴趋亡,色空轮回,动静恒常。", "唯实众名,一理万方,父母爹娘,没齿难忘。", "兄弟姐妹,危困助帮,姑姨叔舅,亲戚互访。", "侄男闺少,哺育茁壮,夫妻相敬,梦忆糟糠。", "隔屋邻舍,遇事谦谅,伯公妪婆,慈孝赡养。", "尊朋礼友,仁义君郎,炎黄二帝,尧舜禅让。", "禹启世袭,灭桀商汤,周武伐纣,侯列各邦。", "秦皇集权,汉刘楚项,鼎立割据,乱晋八王。", "南北对峙,腐朽隋炀,贞观政要,五代续唐。", "陈桥兵变,耻辱靖康,耶律完颜,元建宋僵。", "钟离太祖,崇祯吊丧,清军入关,大臣驻藏。", "粉碎叛卓,犁域设将,台湾复归,守卫边防。", "鸦片战争,英占香港,戊戌维新,社会改良。", "辛亥革命,孙文思想,联盟抗倭,国共两党。", "定都京师,人民解放,诸子百家,孔孟老庄。", "扁鹊灵医,鲁班巧匠,罗盘硝药,针灸疗伤。", "蔡伦毕升,鉴真玄奘,易经论语,史记达畅。", "河图洛书,算术九章,西三红水,聊儒瓶厢。", "诗词曲赋,戏剧说唱,琵琶琴瑟,锣镲铿锵。", "笙箫呜咽,卧笛悠扬,筝音奔奋,唢呐高亢。", "荆浩匡庐,董源潇湘,米芾写意,悲鸿骏昂。", "笔墨纸砚,匾楣楹榜,楷隶篆刻,碑帖草狂。", "敦煌石窟,长城伟墙,青铜甲骨,缕衣纱裳。", "虎符越剑,陶马俑葬,彩瓷宝瓮,丝绸他乡。", "凡尔赛宫,金字塔状,泰姬陵墓,彼得教堂。", "自由女神,希腊塑像,最后晚餐,创造亚当。", "亭榭楼阁,寺庙殿廊,蓬门荜户,丈室绿窗。", "府弟别墅,画栋雕梁,庭院踏步,影屏幕障。", "承尘藻井,篱笆柱桩,舷舵扶靠,凭栏眺望。", "悬崖峭壁,峰峦叠嶂,泉喷岚罩,湍急瀑宕。", "峡沟潭渊,溪涧流淌,池渠堰坝,沼泽泥塘。", "漩涡带波,礁屿连江,汹涌澎湃,惊涛骇浪。", "灾涝溢泻,汛潮浮涨,苍松寿柏,垂柳毛杨。", "芭蕉蒲扇,斑竹篾筐,槐椿榆桦,杉桂榕樟。", "斋扉紧闭,栅苑濒旁,坪埔莱茵,菲窥坞坊。", "蔷薇翩跹,莆菏蔚茫,蕴蒂荚芯,蓓蕾琳琅。", "奇花异卉,艳丽荣秧,兰荷菊梅,四季芬芳。", "杜鹃泣血,芙蓉吉祥,茉莉馥郁,玫瑰刺芒。", "瓜果蔬菜,葱蒜韭姜,茴椒芹葵,皮芥辣酱。", "芸苔芋笋,葫芦瓢瓤,番茄蘑菇,乳蛋醇酿。", "碘盐食醋,脆卜甜糖,珍馐旨甘,肴馔膏粱。", "葡萄美酒,玉液琼浆,咖啡益智,茗茶顺肠。", "桃李杏柿,汁鲜味爽,椰柚橙桔,渴饮品尝。", "菠萝柑橘,橄榄槟榔,梨枣苹楂,荔栗榴棠。", "蝌蚪摆尾,蛤蟆鼓囊,钓饵蚯蚓,蠕虫蚂蟥。", "鹦鹉学舌,蜜蜂穿忙,蝙蝠栖洞,梧桐引凰。", "蜘蛛牵补,螟蛉蛀粮,蜻蜓振翅,鸠鹏张膀。", "鸥莺燕雀,蝴蝶鸳鸯,鲤鲫鲇鲸,蛙蚌螺螃。", "蚜蛾蝉蛹,龟卵翼蝗,蚊蝇鼠蚁,蛇蝎鳝蟒。", "蜈蚣毒腺,蟋蟀蹬闯,鹿狈狐狸,熊豹豺狼。", "猿啼猴吱,鸵孵獭躺,雏猩攀梢,雌牡匿冈。", "砂舟骆驼,迅捷羚羊。"}; String str = strArr[(int)(Math.random()*62)]; return str; } public static String getRandomNum(int length){ //1. 定义一个字符串(A-Z,a-z,0-9)即62个数字字母; String str="1234567890"; //2. 由Random生成随机数 Random random=new Random(); StringBuffer sb=new StringBuffer(); //3. 长度为几就循环几次 for(int i=0; i<length; ++i){ //从10个的数字中选择 int number=random.nextInt(10); //将产生的数字通过length次承载到sb中 sb.append(str.charAt(number)); } //将承载的字符转换成字符串 return sb.toString(); } public static void main(String[] args) { //这里的32是生成32位随机码,根据你的需求,自定义 String random1 = getRandomString(32); System.out.println(random1); String random2 = getRandomNum(32); System.out.println(random2); } }
(7)启动类
import com.lhf.springboot.scheduled.ScheduledExecutorServiceDemo; import com.lhf.springboot.springTask.SpringTaskDemo; import com.lhf.springboot.timer.TimerDemo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication @EnableScheduling //注解开启对定时任务的支持 public class SpringBootTaskJobApplication { public static void main(String[] args) { SpringApplication.run(SpringBootTaskJobApplication.class, args); TimerDemo timerDemo = new TimerDemo(); timerDemo.timerJob(); ScheduledExecutorServiceDemo sch = new ScheduledExecutorServiceDemo(); sch.scheduledJob(); SpringTaskDemo st = new SpringTaskDemo(); st.scheduledCron(); st.scheduledFixedRate(); st.scheduledFixedDelay(); } }
三、启动项目,运行效果如下:
发文不易,如果对你有帮助,请点个赞,感谢你的支持!有问题可以留言!
结束语:人生伟业的建立,不在能知,乃在能行。能行需要坚持,并且认准目标,勇敢前行!