如何安排一个任务只运行一次?
如何安排一个任务只运行一次?
我想延迟执行某项任务,类似于设置一个倒计时器,在一定时间后执行“某事”。
我希望在等待期间保持程序的运行,所以我尝试创建一个包含一分钟延迟的自定义线程:
public class Scratch { private static boolean outOfTime = false; public static void main(String[] args) { Thread countdown = new Thread() { @Override public void run() { try { // 等待一段时间 System.out.println("现在开始一分钟倒计时..."); Thread.sleep(60 * 1000); // 执行某事 outOfTime = true; System.out.println("时间到了!"); } catch (InterruptedException e) { e.printStackTrace(); } } }; countdown.start(); while (!outOfTime) { try { Thread.sleep(1000); System.out.println("在这里做其他事情"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
虽然这种方法基本上能够工作,但似乎应该有更好的方法来实现这个目标。
经过一些搜索,我发现了一些类似的问题,但它们并没有解决我想要做的事情:
- [如何按周期间隔安排任务运行?](https://stackoverflow.com/questions/4544197/how-do-i-schedule-a-task-to-run-at-periodic-intervals)
- [如何每天下午2点运行我的TimerTask?](https://stackoverflow.com/questions/9375882/how-i-can-run-my-timertask-everyday-2-pm)
- [如何使用ScheduledExecutorService在特定时间每天运行某个任务?](https://stackoverflow.com/questions/20387881/how-to-run-certain-task-every-day-at-a-particular-time-using-scheduledexecutorse)
- [Java如何执行带有重试次数和超时的任务?](https://stackoverflow.com/questions/11751329/java-execute-task-with-a-number-of-retries-and-a-timeout)
我不需要这么复杂的东西;我只想在一定时间后执行一次任务,同时让程序的其他部分继续运行。
我应该如何安排一次性任务来执行“某事”?
问题出现的原因是需要在特定的时间点运行一次任务。解决方法是使用调度器和计算得到的时间间隔来安排任务的执行。
具体的解决方法如下所示:
manualTriggerBatchJob.setSchedulingProperties(pblId, batchInterval); ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5); ("unchecked") ScheduledFuture scheduledFuture = scheduledExecutorService.schedule(manualTriggerBatchJob, batchIntervalInMin, TimeUnit.MILLISECONDS);
以上是解决该问题的代码。
如何安排一个任务只运行一次?
在过去,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() { 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(); } }
通过这种方式,您可以获得从调用schedule()
返回的ScheduledFuture<?>
对象。
这允许您摆脱额外的boolean
变量,直接检查作业是否已运行。
如果不想再等待,您还可以通过调用其cancel()
方法取消计划的任务。
这种方法的一个好处是您可以使用CountDownLatch
来替换ScheduleService实现的倒计时对象。
在这个例子中,动作只会运行一次。传递给schedule()
方法的时间是动作运行之前的延迟时间。
如果要持续每1分钟运行此代码,可以如何修改?我的意思是改变代码的行为,与现在相反。
为什么不使用CountDownLatch
来替换ScheduleService实现的倒计时对象?