java之定时任务

来源:http://www.sh-fengwen.com 作者:美高梅游戏平台网站 人气:70 发布时间:2019-09-06
摘要:网络上关于java定时器的文章真的是错误百出,给我的学习造成了很大的困扰, Timer根本就没有线程安全问题,Timer的所有调度方法都和上次任务的结束时间没有关系,TImer和ScheduledThreadPoolEx

网络上关于java定时器的文章真的是错误百出,给我的学习造成了很大的困扰,Timer根本就没有线程安全问题,Timer的所有调度方法都和上次任务的结束时间没有关系,TImer和ScheduledThreadPoolExecutor当任务执行时间大于间隔时间的时候,该task不存在前一次执行还没结束,就再启动执行的情况。只有ScheduledThreadPoolExecutor对该task执行了多次schedulexxx方法、或者多个Timer schedule同一个task,会造成该task的并发。最后通过看源码做测试的方法整理了一些要点。

图片 1图片 2

定时器Timer

Timer的作用是设置定时任务,但封装任务的类是TimerTask,需要程序员继承TimerTask这个抽象类,实现run()方法,放入自己的业务代码。

  1 package com.financial.server.util;
  2 import java.text.SimpleDateFormat;
  3 import java.util.Date;
  4 import java.util.HashMap;
  5 import java.util.Map;
  6 import org.springframework.beans.factory.annotation.Autowired;
  7 import org.springframework.scheduling.annotation.Scheduled;
  8 import org.springframework.stereotype.Component;
  9 
 10 import com.financial.server.service.impl.GSXQ_K_LineOfDayService;
 11 import com.financial.server.service.impl.GSYJReportService;
 12 import com.financial.server.service.impl.HGYJReportService;
 13 import com.financial.server.service.impl.HYYYReportService;
 14 import com.financial.server.service.impl.JuChaoServiceImpl;
 15 import com.financial.server.service.impl.LongHuBangDetailsService;
 16 import com.financial.server.service.impl.QSCHReportService;
 17 import com.financial.server.service.impl.SHZQService;
 18 import com.financial.server.service.impl.SZZQService;
 19 import com.financial.server.service.impl.TZCLReportService;
 20 import com.financial.server.service.impl.TaoGuBaService;
 21 import com.financial.server.service.impl.XGYBReportService;
 22 import com.financial.server.thread.GSYJThread;
 23 import com.financial.server.thread.HGYJThread;
 24 import com.financial.server.thread.HYYYThread;
 25 import com.financial.server.thread.JuChaoDownloadThread;
 26 import com.financial.server.thread.KOfDayThread;
 27 import com.financial.server.thread.LongHuBangDetailsThread;
 28 import com.financial.server.thread.QSCHThread;
 29 import com.financial.server.thread.SHZQThread;
 30 import com.financial.server.thread.SZZQThread;
 31 import com.financial.server.thread.TGBThread;
 32 import com.financial.server.thread.TZCLThread;
 33 import com.financial.server.thread.XGYBThread;
 34 
 35 
 36 @Component  
 37 public class TimerTask { 
 38     @Autowired
 39     private GSXQ_K_LineOfDayService kOfDayService;
 40     
 41     
 42     @Autowired
 43     private JuChaoServiceImpl juChaoServiceImpl;
 44     
 45     @Autowired
 46     private TaoGuBaService taoGuBaService;
 47     
 48     @Autowired
 49     private GSYJReportService gsyjReportService;
 50     @Autowired
 51     private XGYBReportService xgybReportService;
 52     @Autowired
 53     private HYYYReportService hyyyReportService;
 54     /*@Autowired
 55     private GNYBReportService gnybReportService;*/
 56     @Autowired
 57     private TZCLReportService tzclReportService;
 58     @Autowired
 59     private QSCHReportService qschReportService;
 60     @Autowired
 61     private HGYJReportService hgyjReportService;
 62     
 63     @Autowired
 64     private LongHuBangDetailsService longHuBangDetailsService;
 65     
 66     @Autowired
 67     private JuChaoServiceImpl juchChaoServiceImpl;
 68     @Autowired
 69     private GSXQ_K_LineOfDayService gsxq_K_LineOfDayService;
 70     
 71     String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());//
 72     //String date = "2018-07-12";
 73     String typeFile = "F:/巨潮网/巨潮网公告类别.txt";
 74     @Scheduled(cron = "0 59 13 ? * *")//每天15:04执行一次  
 75     public void doSomethingWithCron() {  
 76         try {
 77              
 78              
 79             
 80             //插入跟帖
 81             /*Map<String, String> map = TaoGuBa.webParseHtmls("https://www.taoguba.com.cn/index?blockID=1");
 82             String JessionID = map.get("JSESSIONID").toString();
 83             String cookie = TaoGuBa.SubmitPost(JessionID); 
 84             new Thread(new TGBThread(taoGuBaService, date, date,true)).start();//淘股吧
 85 */            
 86             new Thread(new GSYJThread(gsyjReportService, date, date,true)).start();//公司研究
 87             
 88             new Thread(new XGYBThread(xgybReportService, date, date,true)).start();//新股研报
 89             
 90             new Thread(new HYYYThread(hyyyReportService, date, date,true)).start();//行业研究
 91             
 92             new Thread(new TZCLThread(tzclReportService, date, date,true)).start();//投资策略
 93             
 94             new Thread(new QSCHThread(qschReportService, date, date,true)).start();//券商晨会
 95             
 96             new Thread(new HGYJThread(hgyjReportService, date, date,true)).start();//宏观研究
 97             
 98            new Thread(new LongHuBangDetailsThread(longHuBangDetailsService, date, date,true)).start();//龙虎榜详情
 99             
100             
101             new Thread(new JuChaoThread(juchChaoServiceImpl,typeFile,date, date,true)).start();//巨潮网公告
102             
103             
104             new Thread(new KOfDayThread(gsxq_K_LineOfDayService,date,true)).start();//日k线数据
105             
106              
107             
108         } catch (Exception e) {
109             e.printStackTrace();
110         } 
111     }  
112   
113 }  
Timer的常用方法
  • Timer timer = new Timer()

构造TImer定时器,可以传入boolean参数,true将定时任务设置为守护线程,无参则不设置

  • 构建TimerTask实例

一般都是使用匿名类

TimerTask task = new TimerTask() { public void run() { ... //每次需要执行的业务代码 cancel();//可以让该task退出调度 } };
  • cancel取消全部定时任务

和TimerTask的cancel不同,将全部定时任务都取消

  • schedule调度定时任务

timer.schedule(task, time)

time为Date类型:在指定时间执行一次。

timer.schedule(task, delay)

delay 为long类型,不能小于0,从现在起过delay毫秒执行一次

timer.schedule(task, firstTime, period)

firstTime为Date类型,period为long,从firstTime时刻开始,每隔period毫秒执行一次

timer.schedule(task, delay, period)

delay为long,不能小于0,period为long,从现在起过delay毫秒以后,每隔period毫秒执行一次

View Code

tips

当任务的首次执行时间小于当前时间时,会立即执行,不会做补偿执行,起始时间按照当前时间为基准

验证代码:

Timer timer = new Timer();//耗时2s左右的任务TimerTask task1 = new TimerTask() { @Override public void run() { //获得该任务该次执行的期望开始时间 System.out.println("expect start time: " + new Date(scheduledExecutionTime; System.out.println("task1 start: " + new Date; try { Thread.sleep; } catch (InterruptedException e) {} System.out.println("task1 end: " + new Date; }};Calendar calendar = Calendar.getInstance();calendar.add(Calendar.SECOND, -11);Date date = calendar.getTime();System.out.println("now: " + new Date;System.out.println("timer start: " + date);//设置调度的启动时间为11s前timer.schedule(task1, date, 5000);

结果:

//当前时间16:05:51,设置的启动时间为16:05:40now: Mon Nov 20 16:05:51 CST 2017timer start: Mon Nov 20 16:05:40 CST 2017//立即执行,并将期望的执行时间设为当前时间expect start time: Mon Nov 20 16:05:51 CST 2017task1 start: Mon Nov 20 16:05:51 CST 2017task1 end: Mon Nov 20 16:05:53 CST 2017//以实际的启动时间16:05:51为基准,间隔5秒周期执行,而不按照设置的16:05:40为基准//下一次任务的开始时间以上次任务的开始时间为准,间隔5秒再次执行expect start time: Mon Nov 20 16:05:56 CST 2017task1 start: Mon Nov 20 16:05:56 CST 2017task1 end: Mon Nov 20 16:05:58 CST 2017

可以看出当设置的启动时间小于当前时间时,任务立即执行,并且把当前时间当做基准,间隔5秒再次执行,没有将设置的启动时间为基准

  • scheduleAtFixedRate调度定时任务

timer.scheduleAtFixedRate(task, delay, period)

delay为long,period为long,从现在起过delay毫秒以后,每隔period毫秒执行一次

timer.scheduleAtFixedRate(task, firstTime, period)

firstTime为Date类型,period为long,从firstTime时刻开始,每隔period毫秒执行一次

 

tips

当任务的首次执行时间小于当前时间时,会立即执行,并将之前缺少执行的次数都执行回来,起始时间按照设定的初始时间为基准,atFixedRate的含义是以一种正确的速率执行,也就是一段时间内该执行几次就执行几次,因此会把之前缺少执行的次数补偿回来。

验证代码:

Timer timer = new Timer();//耗时2s左右的任务TimerTask task1 = new TimerTask() { @Override public void run() { //获得该任务该次执行的期望开始时间 System.out.println("expect run time: " + new Date(scheduledExecutionTime; System.out.println("task1 start: " + new Date; try { Thread.sleep; } catch (InterruptedException e) { } System.out.println("task1 end: " + new Date; }};Calendar calendar = Calendar.getInstance();calendar.add(Calendar.SECOND, -11);Date date = calendar.getTime();System.out.println("now: " + new Date;System.out.println("timer start: " + date);//设置调度的启动时间为11s前timer.scheduleAtFixedRate(task1, date, 5000);

结果:

//当前时间15:38:06,设置的启动时间为15:37:55now: Mon Nov 20 15:38:06 CST 2017timer start: Mon Nov 20 15:37:55 CST 2017//期望开始时间小于实际开始时间,追赶进度expect run time: Mon Nov 20 15:37:55 CST 2017task1 start: Mon Nov 20 15:38:06 CST 2017task1 end: Mon Nov 20 15:38:08 CST 2017//期望开始时间小于实际开始时间,追赶进度expect run time: Mon Nov 20 15:38:00 CST 2017task1 start: Mon Nov 20 15:38:08 CST 2017task1 end: Mon Nov 20 15:38:10 CST 2017//期望开始时间小于实际开始时间,追赶进度expect run time: Mon Nov 20 15:38:05 CST 2017task1 start: Mon Nov 20 15:38:10 CST 2017task1 end: Mon Nov 20 15:38:12 CST 2017//期望开始时间小于实际开始时间,追赶进度expect run time: Mon Nov 20 15:38:10 CST 2017task1 start: Mon Nov 20 15:38:12 CST 2017task1 end: Mon Nov 20 15:38:14 CST 2017//进度追上了,以设置的启动时间15:37:55为基准//没有按照上次任务的开始时间15:38:12间隔5秒执行expect run time: Mon Nov 20 15:38:15 CST 2017task1 start: Mon Nov 20 15:38:15 CST 2017task1 end: Mon Nov 20 15:38:17 CST 2017//从此开始正常执行expect run time: Mon Nov 20 15:38:20 CST 2017task1 start: Mon Nov 20 15:38:20 CST 2017task1 end: Mon Nov 20 15:38:22 CST 2017

本文由美高梅游戏平台网站发布于美高梅游戏平台网站,转载请注明出处:java之定时任务

关键词:

最火资讯