java原生实现定时任务:
第一种基于无限循环的的Thread线程方法:
public class ThreadExample {
public static void main(String[] args) {
final long timeInterval = 2000;
Runnable runnable = new Runnable() {
@Override
public void run() {
while(true) {
System.out.println("这是按线程方式来实现的");
try {
Thread.sleep(timeInterval);
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
第二种基于Timer类来实现,属于线程安全的:
public class Task {
public static void main(String[] args) {
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
System.out.println("这是基于timer类来实现的");
}
};
Timer timer = new Timer();
long delay = 0;
long interval = 2000;
timer.schedule(timerTask, delay, interval);
}
}
第三种基于并发工具类ScheduledExecutorService来实现,上面第二种方法是单线程的,而ScheduledExecutorService可以配置线程池也更灵活:
(在web项目上我可以先提供个项目启动就直接运行任务的思路,基于监听器ServletContextListener)
public class Task3 {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
public void run() {
// task to run goes here
System.out.println("这是基于ScheduledExecutorService是实现的");
}
};
ScheduledExecutorService service = Executors
.newSingleThreadScheduledExecutor();
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service.scheduleAtFixedRate(runnable, 10, 1, TimeUnit.SECONDS);
}
}
Spring自带的定时任务:
spring配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<context:component-scan base-package="com.healist.*"/>
//如果单线程就可以满足要求,就可以不写下面三项线程池的配置
<task:executor id="executor" pool-size="5"/>
<task:scheduler id="scheduler" pool-size="10" />
<task:annotation-driven executor="executor" scheduler="scheduler" />
<tx:annotation-driven />
</beans>
web.xml加载spring:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
//加载spring
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext.xml</param-value>
</context-param>
<!-- Spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
log4j配置文件:
log4j.rootLogger=INFO,Console,File
#定义日志输出目的地为控制台
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
#可以灵活地指定日志输出格式,下面一行是指定具体的格式
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n
#文件大小到达指定尺寸的时候产生一个新的文件
log4j.appender.File = org.apache.log4j.RollingFileAppender
#指定输出目录
log4j.appender.File.File = logs/TimerSpider.log
#定义文件最大大小
log4j.appender.File.MaxFileSize = 10MB
# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志
log4j.appender.File.Threshold = ALL
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n
主类的定义,使用Scheduled注解:
package com.healist.timer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class FirstTimer {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Scheduled(cron = "1 * * * * ?")
public void run () {
Date date = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
logger.info("My First Spring Timer:" + df.format(date));
}
}
从运行结果当中可以看到每分钟的第一秒程序就会执行目标函数,看一下下面的参数含义解释你就明白了。
Scheduled注解中cron选项中按顺序依次为
秒
分钟
小时
天
月
星期
年份
所以 “0 20 8 ? * 6L 2016-2025” 这个表达式就代表以下意思:
2016年至2025年的每月的最后一个星期五上午8:20触发。
Scheduled还有很多其它参数,cron还有很多其它参数,想了解更多请自行查阅吧。