学习背景:
当使用接口去获取另一个接口的数据存入数据库的时候,此接口负责频繁去调用另一个接口,那么就需要使用线程和定时任务。在做项目的时候没考虑到这一点就出现了严重的事故,耽误了很多人的很多时间,故此记录。
实现方法:
使用java.util.Timer类:
Timer类允许你调度一个java.util.TimerTask任务,可以是一次性的或者重复执行的。但是,它并不是线程安全的,并且在处理多个任务时可能会有性能问题。
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
// 执行的任务
}
}, delay, period);
测试代码:
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
public class Scheduled {
public static void main(String[] args) {
Timer timer = new Timer();
// 每秒输出当前时间的任务
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// 执行的任务:每秒输出当前时间
System.out.println("当前时间:" + java.time.LocalDateTime.now());
}
}, 0, 1000); // 立即开始,每秒执行一次
// 计算从现在到下一个10:30的时间延迟
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 10);
calendar.set(Calendar.MINUTE, 38);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
// 如果当前时间已经超过了今天的10:30,则设置为明天的10:30
if (System.currentTimeMillis() > calendar.getTimeInMillis()) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
long delay = calendar.getTimeInMillis() - System.currentTimeMillis();
// 每天10点30分执行的任务
timer.schedule(new TimerTask() {
@Override
public void run() {
// 执行的任务:每天10点30分输出信息
System.out.println("任务在 " + java.time.LocalTime.now() + " 执行");
}
}, delay, 24 * 60 * 60 * 1000); // 延迟直到今天的10:30,然后每24小时执行一次
// 注意:在实际应用中,你可能需要考虑Timer的关闭和资源释放
}
}
使用ScheduledExecutorService:
ScheduledExecutorService是Java并发包中的一部分,提供了更强大和灵活的方式来调度任务。它比Timer更推荐使用,因为它支持多线程,可以处理更多的并发任务。
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
scheduler.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// 执行的任务
}
}, initialDelay, period, TimeUnit.SECONDS);
使用java.util.concurrent.DelayQueue:
DelayQueue是一个无界阻塞队列,用于延迟任务的执行。任务只有在延迟期满时才会被取出执行。
DelayQueue<Runnable> queue = new DelayQueue<>();
queue.put(new DelayedTask());
new Thread(new DelayQueueConsumer(queue)).start();
使用Spring框架的@Scheduled注解:
如果你使用Spring框架,可以利用@Scheduled注解来实现定时任务。Spring提供了一个更简洁和声明式的方式来配置定时任务。需要在启动类上开启@EnableScheduling
也可以使用corn表达式。
@Component
public class ScheduledTasks {
@Scheduled(fixedRate = 5000)
public void reportCurrentTime() {
// 执行的任务
}
}
使用Quartz定时任务框架:
Quartz是一个强大的开源作业调度库,可以集成到几乎任何Java应用程序中。它提供了持久化作业和集群支持。
JobDetail job = JobBuilder.newJob(MyJob.class)
.withIdentity("myJob", "group1").build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("myTrigger", "group1")
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
scheduler.scheduleJob(job, trigger);
Quartz官网:Quartz Enterprise Job Scheduler
使用JDK 8的java.time包:
从Java 8开始,你可以使用java.time包中的ScheduledExecutorService来实现定时任务,它提供了比Timer和TimerTask更现代的API。
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(() -> {
// 执行的任务
}, 0, 10, TimeUnit.SECONDS);
使用第三方库如Hystrix:
Hystrix是一个延迟和容错库,它提供了命令模式的抽象,可以用于构建对其他库的调用,包括定时任务。
参考文档:
参考代码:
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class ThreadScheduledTask {
public static void main(String[] args) {
test4();
}
// 第一种方法:设定指定任务task在指定时间time执行 schedule(TimerTask task, Date time)
public static void test1() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
System.out.println("-------延时5秒钟后执行的任务--------");
}
}, 5000);// 设定指定的时间time,此处设置为5000毫秒
}
// 第二种方法:设定指定任务task在五秒后执行,每隔1秒执行一次
// schedule(TimerTask task, long delay, long period)
public static void test2() {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
System.out.println("------五秒后执行的任务,每隔一秒执行一次--------");
}
}, 5000, 1000);
}
// 第三种方法:设定指定任务task在五秒后执行,每隔2秒执行一次
// scheduleAtFixedRate(TimerTask task, long delay, long period)
public static void test3() {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
System.out.println("-------五秒后执行的任务,每隔两秒执行一次--------");
}
}, 5000, 2000);
}
// 第四种方法:安排指定的任务task在指定的时间firstTime开始进行重复的固定速率period执行.
// Timer.scheduleAtFixedRate(TimerTask task,Date firstTime,long period)
public static void test4() {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 11); // 控制时
calendar.set(Calendar.MINUTE, 0); // 控制分
calendar.set(Calendar.SECOND, 0); // 控制秒
Date time = calendar.getTime(); // 得出执行任务的时间,此处为今天的11:00:00
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
System.out.println("-------这是每天11点执行的任务--------");
}
}, time, 1000 * 60 * 60 * 24);// 这里设定将延时每天固定执行
}
}