如何安排任务运行一次?
我想延迟做一些事情,就像设置倒计时器一样,在一段时间后“做一件事”。
我希望程序的其余部分在我等待时继续运行,所以我尝试制作自己的Thread
,其中包含一分钟的延迟:
public class Scratch { private static boolean outOfTime = false; public static void main(String[] args) { Thread countdown = new Thread() { @Override public void run() { try { // wait a while System.out.println("Starting one-minute countdown now..."); Thread.sleep(60 * 1000); // do the thing outOfTime = true; System.out.println("Out of time!"); } catch (InterruptedException e) { e.printStackTrace(); } } }; countdown.start(); while (!outOfTime) { try { Thread.sleep(1000); System.out.println("do other stuff here"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
虽然这或多或少有效,但似乎应该有更好的方法来做到这一点。
经过一番搜索后,我发现了一堆像这样的问题,但它们并没有真正解决我想要做的事情:
- 如何安排任务定期运行?
- 我如何每天下午2点运行我的TimerTask
- 如何使用ScheduledExecutorService在特定时间每天运行某些任务?
- Java执行任务有多次重试和超时
我不需要这么复杂的东西; 我只想在一段时间后做一件事,同时让程序的其余部分仍然运行。
我应该如何安排一次性任务来“做一件事”?
虽然java.util.Timer
曾经是一种安排未来任务的好方法,但现在最好使用java.util.concurrent
包中的类。
有一个ScheduledExecutorService
专门设计用于在延迟后运行命令(或定期执行它们,但这与此问题无关)。
它有一个schedule(Runnable, long, TimeUnit)
方法
创建并执行在给定延迟后启用的一次性操作。
使用ScheduledExecutorService
您可以重写您的程序,如下所示:
import java.util.concurrent.*; public class Scratch { private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); public static void main(String[] args) { System.out.println("Starting one-minute countdown now..."); ScheduledFuture> countdown = scheduler.schedule(new Runnable() { @Override public void run() { // do the thing System.out.println("Out of time!"); }}, 1, TimeUnit.MINUTES); while (!countdown.isDone()) { try { Thread.sleep(1000); System.out.println("do other stuff here"); } catch (InterruptedException e) { e.printStackTrace(); } } scheduler.shutdown(); } }
通过这种方式实现的ScheduledFuture>
是从调用schedule()
返回的ScheduledFuture>
对象。
这允许您摆脱额外的boolean
变量,并直接检查作业是否已运行。
如果您不想再通过调用cancel()
方法再等待,也可以取消计划任务。
1请参阅Java Timer vs ExecutorService? 出于避免使用Timer
而使用ExecutorService
。