Это беспокоит меня уже несколько часов. Если я запланирую выполнение задачи в 5 секунд, а затем немедленно отменю эту задачу, я ожидаю, что метод «awaitTermination» вернется немедленно, но он продолжает блокировать для полного 7 секунд (не пять)..
Вот тестовый пример JUnit 5, который воспроизводит проблему на Java 11.
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");
}
}
Есть идеи?
Вы не вызываете shutdown или shutdownNow для вашего executorService, так что вы можете ждать вечно. Это никогда не прекратится. Сначала вызовите shutdown, тогда модульный тест должен работать.
scheduled.cancel(false);
executorService.shutdown(); // This was missing
if (!executorService.awaitTermination(7, TimeUnit.SECONDS)) {
...
ожиданиетерминация "Блокируется до завершения выполнения всех задач после запроса на отключение, или истечения времени ожидания, или прерывания текущего потока, в зависимости от того, что произойдет раньше" (скопировано из комментариев, спасибо, ptomli).
Может быть полезно добавить ссылку на справочную документацию, в которой говорится > Блокирует до тех пор, пока все задачи не завершат выполнение после запроса на завершение работы, или не истечет время ожидания, или текущий поток не будет прерван, в зависимости от того, что произойдет раньше. docs.oracle.com/javase/8/docs/api/java/util/concurrent/…
Ах, черт, я забыл об этом, когда пытался воспроизвести мою проблему отдельно. Это, очевидно, работает, когда я сначала вызываю выключение. Тогда думаю проблема в другом. Спасибо :-)
Похоже, я борюсь с этим bugs.java.com/bugdatabase/view_bug.do?bug_id=7069418
Из API: «Блокируется до тех пор, пока все задачи не завершат выполнение после запроса на завершение работы, или не истечет время ожидания, или текущий поток не будет прерван, в зависимости от того, что произойдет раньше».