You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中连续调用方法时如何实现异步延迟执行?

问题:调用延迟方法后任务同时执行,需实现间隔1分钟依次输出

我想让每次调用printFirst()方法前延迟1分钟,且不影响主线程运行。用Timer写了如下代码:

// define delaying print-method using Timer
static void printFirst() {
  new java.util.Timer().schedule(
    new java.util.TimerTask() {
      public void run() {
        System.out.println(ts() + " First");
      }
    },60000
  );
}

// main to run
System.out.println(ts() + " Zero");
printFirst();
printFirst();
printFirst();
System.out.println(ts() + " Second");
System.out.println(ts() + " Third");
System.out.println(ts() + " Fourth");

实际输出中三条含“First”的日志同时打印:

Timestamp: 2023-01-05 17:40:43.664 Zero
Timestamp: 2023-01-05 17:40:43.666 Second
Timestamp: 2023-01-05 17:40:43.667 Third
Timestamp: 2023-01-05 17:40:43.667 Fourth
Timestamp: 2023-01-05 17:41:13.681 First
Timestamp: 2023-01-05 17:41:13.681 First
Timestamp: 2023-01-05 17:41:13.681 First

期望三条日志之间间隔1分钟输出:

Timestamp: 2023-01-05 17:40:43.664 Zero
Timestamp: 2023-01-05 17:40:43.666 Second
Timestamp: 2023-01-05 17:40:43.667 Third
Timestamp: 2023-01-05 17:40:43.667 Fourth
Timestamp: 2023-01-05 17:41:43.667 First
Timestamp: 2023-01-05 17:42:43.667 First
Timestamp: 2023-01-05 17:43:43.667 First

问题原因

你每次调用printFirst()都会新建一个java.util.Timer实例,每个Timer独立调度自己的任务,且都设置了60秒的延迟。三次调用几乎在同一瞬间完成,所以三个任务的触发时间完全一致,导致日志同时输出。

解决方案

方案1:复用单个Timer,累加延迟时间

维护一个全局的Timer实例和延迟计数器,每次调用时让延迟时间累加1分钟,确保任务依次推后执行:

import java.util.Timer;
import java.util.TimerTask;

public class DelayedPrint {
    private static final Timer timer = new Timer();
    private static long accumulatedDelay = 0;
    private static final long ONE_MINUTE = 60 * 1000;

    static void printFirst() {
        accumulatedDelay += ONE_MINUTE;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(ts() + " First");
            }
        }, accumulatedDelay);
    }

    private static String ts() {
        return java.time.LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
    }

    public static void main(String[] args) {
        System.out.println(ts() + " Zero");
        printFirst();
        printFirst();
        printFirst();
        System.out.println(ts() + " Second");
        System.out.println(ts() + " Third");
        System.out.println(ts() + " Fourth");
    }
}

方案2:使用ScheduledExecutorService(推荐)

java.util.Timer存在单线程执行、任务异常会导致整个Timer停止的缺陷,更推荐用Java并发包的ScheduledExecutorService,它是更健壮的调度工具:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class DelayedPrint {
    private static final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
    private static long accumulatedDelay = 0;
    private static final long ONE_MINUTE = 1;

    static void printFirst() {
        accumulatedDelay += ONE_MINUTE;
        scheduler.schedule(() -> {
            System.out.println(ts() + " First");
        }, accumulatedDelay, TimeUnit.MINUTES);
    }

    private static String ts() {
        return java.time.LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
    }

    public static void main(String[] args) {
        System.out.println(ts() + " Zero");
        printFirst();
        printFirst();
        printFirst();
        System.out.println(ts() + " Second");
        System.out.println(ts() + " Third");
        System.out.println(ts() + " Fourth");

        // 程序正常结束时关闭调度器,避免线程残留
        // scheduler.shutdown();
    }
}

两种方案都能保证主线程不被阻塞,同时实现三条First日志依次间隔1分钟输出,方案2更适合生产环境使用。

内容的提问来源于stack exchange,提问作者Sangmin Kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 21:55:24