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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM