How to Delay Code Execution in Java – 如何推迟Java中的代码执行

最后修改: 2019年 5月 21日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

It is relatively common for Java programs to add a delay or pause in their operation. This can be useful for task pacing or to pause execution until another task completes.

对Java程序来说,在其操作中添加延迟或暂停是比较常见的。这对于任务的节奏或暂停执行直到另一个任务完成是很有用的。

This tutorial will describe two ways to implement delays in Java.

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

2. A Thread-Based Approach

2.基于线程的方法

When a Java program runs, it spawns a process that runs on the host machine. This process contains at least one thread – the main thread – in which the program runs. Furthermore, Java enables multithreading, which enables applications to create new threads that run in parallel, or asynchronously, to the main thread.

当一个Java程序运行时,它会产生一个进程,在主机上运行。该进程至少包含一个线程–主线程,程序在其中运行。此外,Java支持多线程,这使得应用程序能够创建新的线程,与主线程并行或异步地运行。

2.1. Using Thread.sleep

2.1.使用Thread.sleep

A quick and dirty way to pause in Java is to tell the current thread to sleep for a specified amount of time. This can be done using Thread.sleep(milliseconds):

在Java中,一个快速而肮脏的暂停方法是告诉当前线程睡眠一个特定的时间。这可以用Thread.sleep(milliseconds)来完成。

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

It is good practice to wrap the sleep method in a try/catch block in case another thread interrupts the sleeping thread. In this case, we catch the InterruptedException and explicitly interrupt the current thread, so it can be caught later and handled. This is more important in a multi-threaded program, but still good practice in a single-threaded program in case we add other threads later.

sleep方法包裹在try/catch块中是一个很好的做法,以防其他线程打断正在睡觉的线程。在这种情况下,我们捕获InterruptedException并明确打断当前线程,这样它就可以在以后被捕获并处理。这在多线程程序中更为重要,但在单线程程序中仍然是很好的做法,以备我们以后添加其他线程。

2.2. Using TimeUnit.sleep

2.2.使用TimeUnit.sleep

For better readability, we can use TimeUnit.XXX.sleep(y), where XXX is the time unit to sleep for (SECONDSMINUTES, etc.), and y is the number of that unit to sleep for. This uses Thread.sleep behind the scenes. Here’s an example of the TimeUnit syntax:

为了提高可读性,我们可以使用TimeUnit.XXX.sleep(y),其中XXX是要睡眠的时间单位(SECONDSMINUTES,等等),y是要睡眠的该单位的数量。这在幕后使用Thread.sleep。下面是一个TimeUnit语法的例子。

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

However, there are some disadvantages to using these thread-based methods:

然而,使用这些基于线程的方法也有一些缺点

  • The sleep times are not exactly precise, especially when using smaller time increments like milliseconds and nanoseconds
  • When used inside of loops, sleep will drift slightly between loop iterations due to other code execution so the execution time could get imprecise after many iterations

3. An ExecutorService-Based Approach

3.基于执行者服务的方法

Java provides the ScheduledExecutorService interface, which is a more robust and precise solution. This interface can schedule code to run once after a specified delay or at fixed time intervals.

Java提供了ScheduledExecutorService接口,这是一个更加稳健和精确的解决方案。这个接口可以安排代码在指定的延迟后或在固定的时间间隔内运行一次。

To run a piece of code once after a delay, we can use the schedule method:

为了在延迟后运行一段代码,我们可以使用schedule方法。

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

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

The Classname::someTask part is where we specify the method that will run after the delay:

Classname::someTask部分是我们指定延迟后运行的方法的地方。

  • someTask is the name of the method we want to execute
  • Classname is the name of the class that contains the someTask method

To run a task at fixed time intervals, we can use the scheduleAtFixedRate method:

要以固定的时间间隔运行一个任务,我们可以使用scheduleAtFixedRate方法。

ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

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

This will repeatedly call the someTask method, pausing for delayInSeconds between each call.

这将重复调用someTask方法,每次调用之间停顿delayInSeconds

Besides allowing more timing options, the ScheduledExecutorService method yields more precise time intervals, since it prevents issues with drift.

除了允许更多的计时选项外,ScheduledExecutorService方法产生了更精确的时间间隔,因为它可以防止漂移问题。

4. Conclusion

4.总结

In this article, we discussed two methods for creating delays in Java programs.

在这篇文章中,我们讨论了在Java程序中创建延迟的两种方法。

The full code for this article can be found over on Github. This is a Maven-based project, so it should be easy to import and run as it is.

本文的完整代码可以在Github上找到over。这是一个基于Maven的项目,所以应该很容易导入并按原样运行。