0

我尝试每小时执行一次代码

这适用于可以与服务器一起运行的 applicationRunner 中的 java 启动。

@Component
public class TestApplicationRunner implements ApplicationRunner {
    // some Autowired


    @Override
    public void run(ApplicationArguments args) throws Exception {

        TimerTask repeatedTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("Task performed on " + new Date()); //now

                //Some code that updates the database
            }
        };

        Timer timer = new Timer();
        Calendar date = Calendar.getInstance();

        LocalDateTime nextHour = LocalDateTime.now().plusHours(1).truncatedTo(ChronoUnit.HOURS);
        long result = LocalDateTime.now().until(nextHour, ChronoUnit.MILLIS);

        System.out.println(date.getTime());
        long period = 1000L * 60L * 60L;
        timer.scheduleAtFixedRate(repeatedTask, result, period);

    }
}

如果我在12:34运行这段代码,结果是

        Task performed on 13 : 00 
        Task performed on 14 : 00 
        Task performed on 14 : 00 
        Task performed on 15 : 00 
        Task performed on 15 : 00 
        Task performed on 15 : 00 
        Task performed on 16 : 00 
        Task performed on 16 : 00 
        Task performed on 16 : 00 
        Task performed on 16 : 00
               .....

我想收到

        Task performed on 13 : 00 
        Task performed on 14 : 00 
        Task performed on 15 : 00 
        Task performed on 16 : 00 
        Task performed on 17 : 00 
               .....

我认为线程不止一个,但我不明白为什么他们有多个线程。我添加我的代码。谢谢你的帮助

4

1 回答 1

1

首先:java.util.Timer已经过时了。建议使用java.util.concurrent.ScheduledThreadPoolExecutor代替:

Java 5.0 引入了 java.util.concurrent 包,其中的并发实用程序之一是 ScheduledThreadPoolExecutor,它是一个线程池,用于以给定的速率或延迟重复执行任务。它实际上是 Timer/TimerTask 组合的更通用替代品,因为它允许多个服务线程,接受各种时间单位,并且不需要子类化 TimerTask(只需实现 Runnable)。使用一个线程配置 ScheduledThreadPoolExecutor 使其等效于 Timer。

除此之外,在我看来,您的问题不在于日程安排。您的代码看起来正确。我的猜测是您TestApplicationRunner已多次启动,因此创建了多个计时器。

于 2019-07-25T06:41:05.983 回答