我们可能经常遇到项目需要定时器,如果我们不了解定时器就会用线程去实现,例如:
package org.lzstone.action
public class FinanceAction extends Thread{
private Date date;
public void run{
try{
while(true){
Thread.sleep((int)(Math.random()*1000));
date = new Date();
//定时执行任务
}
}catch(Exception e){
e.printStackTrace();
}
}
}
如果自己实现的定时器实现的不好,内存过多的话系统就会Over,所以处理定时执行或者重复执行的任务,定时器是很好的选择。
定时器我接触的主要是Timer和Quartz,下面就这两种我自己做个简单的介绍:
1.java中常见的定时器
1)借助Java.util.Timer来实现
2)OpenSymphony社区提供的Quartz来实现
2.介绍Timer
利用Timer开发定时任务是主要分为两个步骤:
1)创建定时任务类
示例代码:
package testIsValidLong;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimerTask;
public class TestTimer extends TimerTask {
@Override
public void run() {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = sdf.format(date);
System.out.println(time);
}
}
2)运行定时任务,运行定时任务分为两种方式:
2.1)程序直接启动
示例代码:
package testIsValidLong;
import java.util.Timer;
public class TestTimerMain {
public static void main(String[] args) {
Timer timer = new Timer();
//new LzstoneTimeTask()- 所要安排的任务。
//0- 执行任务前的延迟时间,单位是毫秒。
//1*1000- 执行各后续任务之间的时间间隔,单位是毫秒。
timer.schedule(new TestTimer(), 1000, 1*1000);
}
}
2.2)web监听方式
示例代码:
package org.lzstone.action
public class LzstoneMain implements ServletContextListener{
private Timer timer = null;
//初始化监听器,创建实例,执行任务
public void contextInitialized(ServletContextEvent event){
timer = new Timer();
timer.schedule(new LzstoneTimeTask(),0,1*1000);
}
//销毁监听器,停止执行任务
public void contextDestroyed(ServletContextEvent event){
//注意,在此计时器调用的计时器任务的 run 方法内调用此方法,就可以绝对确保正在执行的任务是此计时器所执行的最后一个任务。
timer.cancel();
}
}
web.xml配置
<listener>
<listener-class>
org.lzstone.action.LzstoneMain
</listener-class>
</listener>
3. 介绍Quartz
Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,可以用来创建简单或者复杂的定时任务,利用Quartz开发定时任务的步骤与Timer类似。
利用Quartz开发定时任务是主要分为两个步骤:
1)创建定时任务类
示例代码:
package com.qlwb.job;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.qlwb.business.po.ClientUser2;
import com.qlwb.business.po.VipInvalid;
import com.qlwb.business.service.VipInvalidService;
/**
* @ClassName: VipInvalidJob
* @Description: 加V失效定时任务
* @author:
* @date 2018年5月31日
*/
public class VipInvalidJob implements Job {
private final Logger logger = Logger.getLogger(VipInvalidJob.class);
private VipInvalidService service = new VipInvalidService();
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
定时业务...
} catch (SQLException e) {
logger.error("xxx出错");
e.printStackTrace();
} catch (ParseException e) {
logger.error("xxx失败");
e.printStackTrace();
}
}
}
2)运行定时任务,运行定时任务分为两种方式:
2.1)程序直接启动,创建任务调度器及配置相应的任务计划
示例代码:
package com.qlwb;
import java.text.ParseException;
import java.util.Date;
import org.apache.log4j.Logger;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import com.aspire.boc.util.ResourceManager;
import com.qlwb.job.ActiveStartEndJob;
import com.qlwb.job.AdPositionPushReportJob;
import com.qlwb.job.HotCommentsNewsJob;
import com.qlwb.job.InformationFlowAdDealJob;
import com.qlwb.job.IntelligenceCommonDealJob;
import com.qlwb.job.IntelligenceSiteCarouselDealJob;
import com.qlwb.job.LifeAdvertStartEndJob;
import com.qlwb.job.LiveFlowSaveJob;
import com.qlwb.job.MsgInfoPushJob;
import com.qlwb.job.NewsAuditDelayJob;
import com.qlwb.job.NewsAuditStatisticsJob;
import com.qlwb.job.NewsCountAndViewsJob;
import com.qlwb.job.NewsPaperParserJob;
import com.qlwb.job.NoPayOrderDeal;
import com.qlwb.job.ProductStartEndJob;
import com.qlwb.job.PushNewsJob;
import com.qlwb.job.QlwbReporterJob;
import com.qlwb.job.QlydFlowRechargeJob;
import com.qlwb.job.QlydFlowRechargeResultJob;
import com.qlwb.job.RedMoneyPackageJob;
import com.qlwb.job.SmartCommunityCountJob;
import com.qlwb.job.VipInvalidJob;
import com.qlwb.job.YouliaoNewsPullJob;
import com.qlwb.job.mq.AddTicketReqCustomer;
import com.qlwb.job.mq.ClientUserGrapCustomer;
import com.qlwb.job.mq.EsDataStatusDealCustomer;
import com.qlwb.job.mq.GrapMoneyPackageConsumer;
import com.qlwb.job.mq.IntelligenceUserStatusPushCustomer;
import com.qlwb.job.mq.NewsListUpdateDealCustomer;
import com.qlwb.job.mq.PushMsgToAppCustomer;
import com.qlwb.job.mq.PushNewsCustomer;
import com.qlwb.job.mq.QlwbAddNewsRecordCustomer;
import com.qlwb.job.mq.QlydAddPicWaterCustomer;
import com.qlwb.job.mq.QlydAutoNewsCommentCustomer;
import com.qlwb.job.mq.TransVideoCodeCustomer;
import com.qlwb.job.mq.UserCreditsOptCustomer;
import com.qlwb.job.mq.UserFeedBackPushCustomer;
import com.qlwb.job.mq.VideoTranscodingCustomer;
import com.qlwb.job.mq.ViewCountIncrCustomer;
import com.qlwb.thread.AdPositionTread;
import com.qlwb.thread.AppOpenImgThread;
import com.qlwb.thread.AuditNewsAssignThread;
import com.qlwb.thread.DealGrabPackageThread;
public class MainEntry {
private static final Logger logger = Logger.getLogger(MainEntry.class);
public static void main(String args[]) {
ResourceManager rm = ResourceManager.getInstance();
AppOpenImgThread appOpenImgThread = new AppOpenImgThread();
appOpenImgThread.start();
SchedulerFactory schedFact = new StdSchedulerFactory();
try {
Scheduler Sched = schedFact.getScheduler();
String[] jobs = Sched.getJobNames(Scheduler.DEFAULT_GROUP);
if (jobs.length == 0) {
//用户vip失效
JobDetail vipInvalidDetail = new JobDetail(
"vipInvalidJob", Scheduler.DEFAULT_GROUP,
VipInvalidJob.class);
Trigger vipInvalidTrigger = null;
if (!"-".equals(rm.getValue("Timer.vipInvalidTrigger"))) {
vipInvalidTrigger = new CronTrigger(
"vipInvalidJob", Scheduler.DEFAULT_GROUP,
rm.getValue("Timer.vipInvalidTrigger"));
}
if (vipInvalidTrigger != null) {
Sched.scheduleJob(vipInvalidDetail,
vipInvalidTrigger);
}
}
Sched.start();
} catch (SchedulerException e) {
logger.error(
"InitQuartzJob.main SchedulerException:" + e.getMessage(),
e);
} catch (ParseException e) {
logger.error("InitQuartzJob.main ParseException:" + e.getMessage(),
e);
} catch (Exception e) {
logger.error("InitQuartzJob.main Exception:" + e.getMessage(), e);
}
}
}
2.2)web监听方式
示例代码:
package org.lzstone.action
public class LzstoneMainListener implements ServletContextListener{
private Timer timer = null;
//初始化监听器,创建实例,执行任务
public void contextInitialized(ServletContextEvent event){
LzstoneMain.run();
}
//销毁监听器,停止执行任务
public void contextDestroyed(ServletContextEvent event){
LzstoneMain.stop();
}
}
web.xml配置
<listener>
<listener-class>
org.lzstone.action.LzstoneMainListener
</listener-class>
</listener>
4.对比
Timer方式实现定时器,原理简单,实现方便,在执行简单的任务比较方便,不足之处是无法确定执行时间,并且依赖性比较强,必须继承指定的类
Quartz方式实现定时器,方便,清晰指定启动时间,定时参数比较灵活,容易实现比较复杂的定时任务,不足之处是需要实现特定接口,加载其框架
两种方式各有优缺点,在特定场合可以根据其特点选择使用。