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

之前我用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

时间: 2024-10-05 04:45:09

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

java web项目(spring项目)中集成webservice ,实现对外开放接口

什么是WebService?webService小示例 点此了解 下面进入正题: Javaweb项目(spring项目)中集成webservice ,实现对外开放接口步骤: 准备: 采用与spring兼容性较好的cxf来实现 cxf 的  jar下载地址: http://cxf.apache.org/download.html 选择zip格式下载,解压后的lib目录下的jar 需要最少的jar如下: cxf-2.3.3.jargeronimo-annotation_1.0_spec-1.1.1.

使用junit4测试spring项目中service方法

使用junit4测试项目中service方法 1 import java.util.HashMap; 2 import java.util.List; 3 import java.util.Map; 4 5 import javax.annotation.Resource; 6 7 import org.junit.Test; 8 import org.junit.runner.RunWith; 9 import org.springframework.test.context.ContextC

在spring项目中,普通类注入获取Bean,实现ApplicationContextAware接口

在平时spring项目中,某个不能注入Bean的项目中要获取Bean. @Component public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext = null; public SpringUtil() { } public void setApplicationContext(ApplicationContext arg0

在Spring项目中使用@Scheduled注解定义简单定时任务

如题所示,有时候我们需要在Web项目中配置简单的定时任务,而且因为任务并不复杂不想使用定时调度框架(PS:Quartz.ActiveMQ .Kafka等),这时就可以考虑使用@Scheduled注解来定义简单的定时任务.其全部配置如下: (1)在Spring的配置文件中添加定时任务相关配置: xml配置的头文件中添加: xmlns:task="http://www.springframework.org/schema/task" 以及在xsi:schemaLocation中添加: ht

Spring Boot 中实现定时任务的两种方式

在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Quartz ,Spring Boot 源自 Spring+SpringMVC ,因此天然具备这两个 Spring 中的定时任务实现策略,当然也支持 Quartz,本文我们就来看下 Spring Boot 中两种定时任务的实现方式. @Scheduled 使用 @Scheduled 非常容易,直接创建一个

Spring项目中Properties不能加载多个的问题

A模块和B模块都分别拥有自己的Spring XML配置,并分别拥有自己的配置文件: A模块 A模块的Spring配置文件如下: Xml代码   <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSch

web项目中添加定时任务

1.在web.xml中添加servlet <servlet> <servlet-name>StatisticInitServlet</servlet-name> <servlet-class>com.jovision.servlet.StatisticInitServlet</servlet- class> <load-on-startup>1</load-on-startup> 该servlet加载顺序,设为1,数字越小

spring项目中web-inf下不能引用页面资源

1.spring项目结构 2.spring结构说明 web-inf目录是不对外开放的,外部没办法直接访问到(即通过url访问),只有通过映射来访问,如映射一个action或servlet通过服务器端跳转来访问到具体的页面,这样可以限制访问,提高安全性 页面资源文件只能放在webapp文件下,若css.js.image等文件放在web-inf下是引用不了的

spring 项目中使用 hibernate validator验证输入参数

1 hibernate validator 官方文档:https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/ 在 springboot 项目中 spring-boot-starter-web 已经包含了 hibernate-validator 可以直接使用.否则需要在 maven 依赖中添加依赖项. <dependency> <groupId>org.hibernate.valid