我想每天下午2点执行一份工作。
java.util.Timer
我可以使用哪种方法安排工作?
2小时后,它将停止工作,并在下午2点重新安排工作。
答案 0 :(得分:54)
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 2);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
// every night at 2am you run your task
Timer timer = new Timer();
timer.schedule(new YourTask(), today.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)); // period: 1 day
答案 1 :(得分:22)
您可以使用Timer.schedule(TimerTask task, Date firstTime, long period)
方法,将firstTime
设置为今天下午2点,将period
设置为24小时:
从指定时间开始,为重复的固定延迟执行计划指定的任务。随后的执行大约定期进行,以指定的时间段分开。
答案 2 :(得分:15)
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;
public class MyTimerTask extends TimerTask {
private final static long ONCE_PER_DAY = 1000*60*60*24;
//private final static int ONE_DAY = 1;
private final static int TWO_AM = 2;
private final static int ZERO_MINUTES = 0;
@Override
public void run() {
long currennTime = System.currentTimeMillis();
long stopTime = currennTime + 2000;//provide the 2hrs time it should execute 1000*60*60*2
while(stopTime != System.currentTimeMillis()){
// Do your Job Here
System.out.println("Start Job"+stopTime);
System.out.println("End Job"+System.currentTimeMillis());
}
}
private static Date getTomorrowMorning2AM(){
Date date2am = new java.util.Date();
date2am.setHours(TWO_AM);
date2am.setMinutes(ZERO_MINUTES);
return date2am;
}
//call this method from your servlet init method
public static void startTask(){
MyTimerTask task = new MyTimerTask();
Timer timer = new Timer();
timer.schedule(task,getTomorrowMorning2AM(),1000*10);// for your case u need to give 1000*60*60*24
}
public static void main(String args[]){
startTask();
}
}
答案 3 :(得分:4)
我发现这样做的最简单方法一直是通过Windows中的Task Scheduler和Linux中的cron。
但是对于Java,请查看Quartz Scheduler
从他们的网站:
Quartz是一个功能齐全的开源作业调度服务 与几乎任何Java EE或Java集成或一起使用 SE应用程序 - 从最小的独立应用程序到 最大的电子商务系统。 Quartz可用于创建简单或 执行数十,数百甚至甚至的复杂计划 成千上万的工作;任务被定义为标准的作业 Java组件,可以执行您可能编程的几乎任何内容 他们这样做。 Quartz Scheduler包含许多企业级 功能,例如JTA事务和群集。
答案 4 :(得分:3)
您应该尝试使用scheduleAtFixedRate(这将重复您的任务)。您将需要创建一个TimerTask对象,该对象将指定要运行的内容(在run()中)和何时运行(scheduledExecutionTime)。 scheduleAtFixedRate还允许您指定第一个执行日期。
答案 5 :(得分:2)
为什么不使用Spring的@Scheduled(cron =" 0 0 14 * * *")..秒,分钟,小时,日,月,日我们周。 V酷。您甚至可以在9:00到11:00指定9-11,或在最后一个参数指定MON-FRI。 您也可以以编程方式调用此方法,就像大多数Spring的情况一样,以防您想在运行时设置时间。 看到这个: - http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html
添加示例
@Scheduled(cron="0 0 14 * * *")
public void customScheduler(){
try{
// do what ever you want to run repeatedly
}catch(Exception e){
e.printStackTrace();
}
}
还请使用@Component注释注释包含此类的类,并在Application.java(类包含main方法)类中提供@EnableScheduling,以使spring意识到您在应用程序中使用了taskscheduler。
答案 6 :(得分:1)
使用public void schedule(TimerTask任务,Date firstTime,long period)
使第二天再次重复任务,只需将时间段设置为86400000毫秒(即1天)
Date date2pm = new java.util.Date();
date2pm.setHour(14);
date2pm.setMinutes(0);
Timer timer = new Timer();
timer.sc(myOwnTimerTask,date2pm, 86400000);
答案 7 :(得分:1)
Java 5.0引入了java.util.concurrent软件包,其中之一是 其中的并发实用程序是ScheduledThreadPoolExecutor 是用于以给定速率重复执行任务的线程池,或者 延迟。实际上,它是多功能的替代品 Timer / TimerTask组合,因为它允许多个服务线程, 接受各种时间单位,不需要子类化TimerTask (只需实现Runnable)。配置ScheduledThreadPoolExecutor 一个线程使它等效于Timer。
所以(将此代码添加到您的班级中):
private ScheduledExecutorService scheduledExecutorService;
public ScheduledSendLog() {
init();
}
public void destroy() {
this.scheduledExecutorService.shutdown();
}
private void init() {
scheduledExecutorService =
Executors.newScheduledThreadPool(1);
System.out.println("---ScheduledSendLog created " + LocalDateTime.now());
startSchedule(LocalTime.of(02, 00));
}
private void startSchedule(LocalTime atTime) {
this.scheduledExecutorService.scheduleWithFixedDelay(() -> {
System.out.println(Thread.currentThread().getName() +
" | scheduleWithFixedDelay | " + LocalDateTime.now());
// or whatever you want
}, calculateInitialDelayInSec(atTime),
LocalTime.MAX.toSecondOfDay(),
TimeUnit.SECONDS);
}
private long calculateInitialDelayInSec(LocalTime atTime) {
int currSec = LocalTime.now().toSecondOfDay();
int atSec = atTime.toSecondOfDay();
return (currSec < atSec) ?
atSec - currSec : (LocalTime.MAX.toSecondOfDay() + atSec - currSec);
}
答案 8 :(得分:1)
此问题和以下两个问题的大多数答案假设每天的毫秒数始终相同。
How to schedule a periodic task in Java?
How to run certain task every day at a particular time using ScheduledExecutorService?
但是,由于节省日光和leap秒,因此无法实现。 这意味着,如果您的服务可以使用多年,并且计时器的准确性至关重要, 固定时间计时器不是您的选择。
因此,我想介绍我的代码段,以提供比java.util.Timer
更灵活的计时器。
package szx;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Function;
public class ScheduledExecutor {
public void scheduleRegularly(Runnable task, LocalDateTime firstTime,
Function<LocalDateTime, LocalDateTime> nextTime) {
pendingTask = task;
scheduleRegularly(firstTime, nextTime);
}
protected void scheduleRegularly(LocalDateTime firstTime,
Function<LocalDateTime, LocalDateTime> nextTime) {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
scheduleRegularly(nextTime.apply(firstTime), nextTime);
pendingTask.run();
}
}, Date.from(firstTime.atZone(ZoneId.systemDefault()).toInstant()));
}
private volatile Runnable pendingTask = null;
}
然后,您可以通过以下方式调用上述方法来每天下午2点执行工作。
new ScheduledExecutor().scheduleRegularly(() -> {
// do your task...
}, LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).withHour(14), thisTime -> thisTime.plusDays(1));
代码的基本思想是重新计算到下一个刻度的剩余时间,并每次都启动一个新计时器。