какие другие причины не могут отменить задачу?

62
7

"boolean cancel (boolean mayInterruptIfRunning) Попытка отменить выполнение этой задачи. Эта попытка потерпит неудачу, если задача уже завершена, уже отменена или не может быть отменена по какой-либо другой причине "

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)

Помимо причин, перечисленных выше, какие другие причины не могут отменить задачу? Также, если задача запустить код, как показано ниже, может быть отменена?

while(true)
{
;
}

спросил(а) 2021-01-19T18:53:01+03:00 2 месяца, 3 недели назад
1
Решение
75

Цикл while, который вы публикуете, будет примером кода без отмены, поскольку он не реагирует на прерывание.

Код, блокирующий прослушивание сокета, также может не работать с прерыванием. Даже если время ожидания кода прерывается с InterruptedIOException, если вы проглотите исключение без установки флага прерывания, тогда код может не работать с прерыванием.

Так TL;DR: 1) код, который блокирует IO 2) код, который не обращает внимания на то, как работает прерывание. Или сочетание того и другого.

ответил(а) 2021-01-19T18:53:01+03:00 2 месяца, 3 недели назад
45

На самом деле нет хорошего способа прекратить поток в Java. Вы можете в принципе сказать, что поток останавливается, но поток может постоянно ждать и никогда не читает флаг или подобные проблемы. На самом деле это своего рода сложная проблема. Поэтому я предполагаю, что вместо этого они просто сказали "какую-то проблему".

ответил(а) 2021-01-19T18:53:01+03:00 2 месяца, 3 недели назад
44

Каждый поток имеет специальный флаг, который содержит состояние прерывания, доступное с помощью метода isInterrupted(). Когда кто-то прерывает поток, этот флаг имеет значение true. Все это. Никакого реального прерывания не происходит, пока код, выполняемый этим потоком, не проверяет этот флаг и не выдает InterruptedException или просто прекращает выполнение потока, если это возможно.

Многие методы в стандартной библиотеке, которые предназначены для блокировки текущего потока, на самом деле проверяют этот флаг время от времени и бросают InterruptedException когда они обнаружили, что флаг установлен. Например, Thread.sleep(), Thread.join(), Object.wait(), Lock.lockInterruptibly() и многие другие. Следовательно, когда ваш поток периодически проверяет этот флаг явно или блокируется некоторыми из описанных методов, которые проверяют его неявно, он прерывается. В противном случае это не так.

Таким образом, поток с пустым циклом не может быть прерван, потому что он не проверяет статус прерывания. Но добавление проверки состояния прерывания исправит это:

while (!Thread.currentThread().isInterrupted()) { }

Вызов метода, реагирующего на прерывания, также будет работать:

try {
while (true) {
Thread.sleep(timeout);
}
} catch(InterruptedException e) {
// Do nothing, just let the thread exit
}

ответил(а) 2021-01-19T18:53:01+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема