Java 中如何延迟代码执行

更新于 2025-12-29

Jacob Stopak 2025-03-26

1. 引言

在 Java 程序中,为操作添加延迟或暂停是一种相对常见的需求。这在控制任务节奏、或等待其他任务完成后再继续执行时非常有用。

本教程将介绍两种在 Java 中实现延迟的方法。

2. 基于线程(Thread)的方法

当 Java 程序运行时,它会在主机上启动一个进程。该进程至少包含一个线程——主线程(main thread),程序就在这个线程中运行。此外,Java 支持多线程,允许应用程序创建新的线程,这些线程可以与主线程并行(或异步)运行。

2.1 使用 Thread.sleep

在 Java 中快速实现暂停的一种简单方法是让当前线程“休眠”一段指定的时间。这可以通过 Thread.sleep(milliseconds) 实现:

try {
    Thread.sleep(secondsToSleep * 1000);
} catch (InterruptedException ie) {
    Thread.currentThread().interrupt();
}

建议将 sleep 方法包裹在 try/catch 块中,以防其他线程中断正在休眠的线程。在这种情况下,我们捕获 InterruptedException 并显式地中断当前线程,以便稍后能被正确处理。这在多线程程序中尤为重要,但在单线程程序中也属于良好实践,以防将来添加其他线程。

2.2 使用 TimeUnit.sleep

为了提高代码可读性,我们可以使用 TimeUnit.XXX.sleep(y),其中 XXX 是时间单位(如 SECONDSMINUTES 等),y 是要休眠的单位数量。该方法底层仍使用 Thread.sleep。以下是 TimeUnit 的用法示例:

try {
    TimeUnit.SECONDS.sleep(secondsToSleep);
} catch (InterruptedException ie) {
    Thread.currentThread().interrupt();
}

然而,使用这些基于线程的方法存在一些缺点:

  • 休眠时间并不完全精确,尤其是在使用毫秒或纳秒等较小时间单位时;
  • 在循环中使用 sleep 时,由于每次循环中其他代码的执行时间不同,会导致休眠时间产生轻微“漂移”(drift),经过多次迭代后,整体执行时间可能变得不准确。

3. 基于 ExecutorService 的方法

Java 提供了 ScheduledExecutorService 接口,这是一种更健壮且精确的解决方案。该接口可以安排代码在指定延迟后执行一次,或以固定时间间隔重复执行。

要延迟执行某段代码一次,可以使用 schedule 方法:

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

executorService.schedule(Classname::someTask, delayInSeconds, TimeUnit.SECONDS);

其中 Classname::someTask 指定了延迟后要执行的方法:

  • someTask 是要执行的方法名;
  • Classname 是包含该方法的类名。

若要以固定时间间隔重复执行任务,可使用 scheduleAtFixedRate 方法:

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

executorService.scheduleAtFixedRate(Classname::someTask, 0, delayInSeconds, TimeUnit.SECONDS);

上述代码会反复调用 someTask 方法,并在每次调用之间暂停 delayInSeconds 秒。

除了提供更灵活的定时选项外,ScheduledExecutorService 还能提供更精确的时间间隔,因为它能有效避免因代码执行时间波动导致的“漂移”问题。

4. 结论

本文介绍了在 Java 程序中创建延迟的两种方法:

  • 使用 Thread.sleepTimeUnit.sleep 实现简单但精度较低的延迟;
  • 使用 ScheduledExecutorService 实现更精确、功能更丰富的定时任务调度。

根据具体需求选择合适的方法,可以有效提升程序的可靠性和可维护性。