我正在使用Spring的TaskScheduler来安排定期任务。
ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
我知道我可以在ScheduledFuture上调用cancel()来停止执行重复任务。但我想根据执行任务的结果取消定期计划任务,并且不确定如何做到最好。
ScheduledFuture是否允许我访问每个执行任务的结果?或者我是否需要某种可以保留对此ScheduledFuture的引用的任务侦听器,并以这种方式取消它?或其他什么?
答案 0 :(得分:1)
好吧看起来有可能,但可能有更好的方法。
由于重复作业只接受Runnable(具有void返回类型),因此无法返回任务结果。因此,停止重复任务的唯一方法是使任务执行副作用,例如:向队列添加停止消息。然后,一个单独的线程需要监视此队列,并且一旦看到该消息就可以取消该作业。
非常混乱和复杂。
更好的选择是创建正常(一次)计划任务。然后,任务本身可以决定是否需要安排另一个任务,并且可以自己安排下一个任务。
答案 1 :(得分:1)
保留句柄或原始固定费率ScheduledFuture
,然后当您想要取消它的情况出现时,安排执行取消的新任务。
您也可以使用RunnableScheduledFuture
执行某些操作。
来自ScheduledExecutorService
文档
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html
import static java.util.concurrent.TimeUnit.*;
class BeeperControl {
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public void beepForAnHour() {
final Runnable beeper = new Runnable() {
public void run() { System.out.println("beep"); }
};
final ScheduledFuture<?> beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
scheduler.schedule(new Runnable() {
public void run() { beeperHandle.cancel(true); }
}, 60 * 60, SECONDS);
}
}
答案 2 :(得分:0)
这是一个经过修改的蜂鸣器示例,演示了如何在每个EACH计划任务之后做出决定。我使用了一个闩锁,因此可以将其包装在测试用例中,并断言正确的事情发生了(当然也可以防止测试运行器的线程停止运行)。我还更改了时间间隔(在最初的10ms延迟后每10ms发出哔声),以便可以在一秒钟内复制,粘贴和执行测试,而不是一个小时。
import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class BeeperTest {
class BeeperControl {
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, (runnable) -> {
Thread thread = new Thread(runnable);
thread.setName("MyAwesomeBeeperTestThread");
thread.setDaemon(true);
return thread;
});
public void beepTheNumberOfTimesIWant(CountDownLatch latch) {
long initialDelay = 10;
long frequency = 10;
TimeUnit unit = TimeUnit.MILLISECONDS;
final int numberOfTimesToBeep = 5;
AtomicInteger numberOfTimesIveBeeped = new AtomicInteger(0);
final ScheduledFuture[] beeperHandle = new ScheduledFuture[1];
beeperHandle[0] = scheduler.scheduleAtFixedRate(() -> {
if (numberOfTimesToBeep == numberOfTimesIveBeeped.get()) {
System.out.println("Let's get this done!");
latch.countDown();
beeperHandle[0].cancel(false);
}
else {
System.out.println("beep");
numberOfTimesIveBeeped.incrementAndGet();
}
}, initialDelay, frequency, unit);
}
}
@Test
public void beepPlease() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(1);
BeeperControl control = new BeeperControl();
control.beepTheNumberOfTimesIWant(latch);
boolean completed = latch.await(1, TimeUnit.SECONDS);
Assert.assertTrue("Beeper should be able to finish beeping" +
"within allotted await time.", completed);
}
}