【问题标题】:Cancelling a task scheduled in a ScheduledExecutorService keeps executor alive取消 ScheduledExecutorService 中计划的任务使执行器保持活动状态
【发布时间】:2019-03-12 15:04:40
【问题描述】:

这已经困扰我几个小时了。如果我安排一个任务在 5 秒 内执行,然后立即取消该任务,我希望“awaitTermination”方法立即返回,但它会一直阻塞整个 7 秒(不是 5 秒)..

这是一个在 Java 11 上重现该问题的 JUnit 5 测试用例。

package dummy;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

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.AtomicBoolean;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.fail;

class DummyTest {

  @Test
  @DisplayName("Cancelling task should work...")
  void cancel_task() throws InterruptedException {
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

    AtomicBoolean isExecuted = new AtomicBoolean(false);
    ScheduledFuture<?> scheduled = executorService.schedule(() -> isExecuted.set(true), 5, TimeUnit.SECONDS);
    scheduled.cancel(false);

    if (!executorService.awaitTermination(7, TimeUnit.SECONDS)) {
      fail("Didn't shut down within timeout"); // <-- Fails here
    }

    assertFalse(isExecuted.get(), "Task should be cancelled before executed");
  }

}

有什么想法吗?

【问题讨论】:

  • 来自API:“在关闭请求后阻塞,直到所有任务完成执行,或者发生超时,或者当前线程被中断,以先发生者为准。”

标签: java scheduledexecutorservice


【解决方案1】:

您不会在 executorService 上调用 shutdown 或 shutdownNow,因此您可以永远等待。它永远不会终止。先调用shutdown,然后单元测试就可以工作了。

scheduled.cancel(false);
executorService.shutdown(); // This was missing
if (!executorService.awaitTermination(7, TimeUnit.SECONDS)) {
...

awaitTermination "阻塞直到所有任务完成执行关闭请求后,或超时,或当前线程被中断,以先发生者为准"(复制自 cmets,感谢 ptomli) .

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
相关资源
最近更新 更多