在ScheduledExecutorService中运行的任务本身内停止定期任务

aka*_*okd 21 java concurrency anonymous-class executorservice variable-initialization

在ScheduledExecutorService中运行时,是否有一种很好的方法可以阻止任务内部重复任务?

可以说,我有以下任务:

Future<?> f = scheduledExecutor.scheduleAtFixedRate(new Runnable() {
    int count = 0;
    public void run() {
       System.out.println(count++);
       if (count == 10) {
           // ??? cancel self
       }
    }
}, 1, 1, TimeUnit.SECONDS);
Run Code Online (Sandbox Code Playgroud)

从外面看,很容易通过f.cancel()取消,但是如何在指定的地方停止重复?(通过AtomicReference传递Future是不安全的,因为当scheduleAtFixedRate返回f迟到且变量设置得太晚时,有一个潜在的窗口,并且任务本身可能已经运行,在引用中看到null.)

Pet*_*rey 14

当重复任务抛出异常或错误时,它将被置于Future中,并且不会再次重复该任务.您可以抛出您选择的RuntimeException或Error.

  • 这是最好的方法.如果你想让它"漂亮",则声明一个扩展RuntimeException的类,它正确地描述了TaskComplete等目的. (3认同)
  • 不会这样做会导致长时间运行的进程中的内存泄漏,因为对可运行的引用仍将由scheduledExecutor保留? (2认同)

Reb*_*oot 5

您可以使用命名类而不是使用匿名内部类,该类可以为FutureExecutor在安排任务时从中获取的对象提供一个属性。

abstract class FutureRunnable implements Runnable {

    private Future<?> future;

    /* Getter and Setter for future */

}
Run Code Online (Sandbox Code Playgroud)

当您安排任务时,您可以将 传递FutureRunnable.

FutureRunnable runnable = new FutureRunnable() {

    public void run() {
        if (/* abort condition */)
            getFuture().cancel(false);
    }

};
Future<?> future = executor.scheduleAtFixedRate(runnable, ...);
runnable.setFuture(future);
Run Code Online (Sandbox Code Playgroud)

也许您必须确保Future在设置之前不会执行任务,否则您将获得NullPointerException.

  • NPE 将有效地取消任务一样好:) (2认同)