Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 374|回复: 0

spring项目中的定时任务实现和问题解决

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-6 17:39:19 | 显示全部楼层 |阅读模式

    之前我用JAVA中的Timer类实现了服务器的定时任务,具体详见之前的博文。

    后来发现了一个更简单的实现方式,利用spring中的@Scheduled注解实现觉得简单的很多。

    确实spring封装的特别好,实现起来比原来简单多了。

    下面是配置。

     

    在spring的xml配置中最上面加入

    xmlns:task=http://www.springframework.org/schema/task

    xsi:schemaLocation中加入

    http://www.springframework.org/schema/task 

    http://www.springframework.org/schema/task/spring-task-3.1.xsd 

    在后面加入

    <!-- 用于定时器的配置 -->

    <task:annotation-driven/>

     

    最后写一个定时器的类就行了,写法可以和controller类似,上面的注解不一样而已

    @Component
    public class TimeTask {
        
        @Autowired
        public IUserService userService;
        
        @Scheduled(cron="0/5 * *  * * ? ")
        public void test()
        {
            System.out.println("11111111111111111111111111111111111");
        }
    }

    然后运行项目你就能发现每5秒执行一次

     

     

    然后发现两个使用上面的问题。

    问题1:如果配置了多个定时任务,当有任务1执行时间过长的时候会阻塞任务2

    如下面所示

    @Component
    public class TimeTask {
        
        @Autowired
        public IUserService userService;
        
        @Scheduled(cron="0/5 * *  * * ? ")
        public void test()
        {
            System.out.println("11111111111111111111111111111111111");
        }
        
        @Scheduled(cron="0/1 * *  * * ? ")
        public void test2() throws InterruptedException
        {
            TimeUnit.SECONDS.sleep(10);//模拟延时10秒
            System.out.println("222222222222222222222222222222222");
        }
        
    }

    你会发现11111和22222是同时打印的,1111并不是5秒打印一次了。所以你需要配置线程池。

    把之前的spring中的配置修改为下面这样,20是线程池的大小,根据具体项目需求来设置。

    <task:annotation-driven scheduler="myScheduler"/>
        <task:scheduler id="myScheduler" pool-size="20"/>

     

    问题2,定时任务莫名其妙被执行两次。

    一开始就发现了这个问题,莫名其妙会输出111111和111111两次。连续两次。

    就相当任务被同时执行了两次,一开始我觉得奇怪,但是后来查询资料发现了我的一个大问题。

    在web。xml中加载了两次相同的spring配置

    就相当于spring的上下文被创建了两次,导致定时任务也就创建了两次,所以导致这个问题的发生

    一开始的配置

    <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:config/applicationContext.xml</param-value>
        </context-param>
        <servlet>
            <servlet-name>springMVC_dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath*:config/applicationContext.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>

    加载两个applicationContext

    后面修改成了两个配置文件

    <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:config/beans.xml</param-value>
        </context-param>
        <servlet>
            <servlet-name>springMVC_dispatcher</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath*:config/applicationContext.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>

    一个加载定时器和controller的相关配置,一个加载数据库相关配置。

    然后就解决了。

    下面是stackoverflow中对这个问题的描述

    http://stackoverflow.com/questions/3672289/spring-3-scheduled-task-running-3-times

    深层次的原因可以看我的另一篇博文

    http://www.cnblogs.com/linkstar/p/5782027.html

     

    下面转载一个定时器时间上面的配置,因为定时器的时间配置不好记,所以暂时记录一下,和linux上面的定时任务很像。

    http://rainbowdesert.iteye.com/blog/2107220

     

    最后是spring官网的文档,我没看,英文不好

    http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-3 23:40 , Processed in 0.065412 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表