2016-08-31 3 views
1

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

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

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

while(true) 
{ 
; 
} 
+0

Там может быть любое количество причин, но все они подпадают под категорию " задача не останавливается, несмотря на ваш запрос на отмену ». Ваш while-true цикл будет одной из тех многих причин. –

+0

@ Erwin, Есть ли у них какие-либо правила \ шаблоны? – Jason

+0

также могут быть отменены любые типы задач, любые шаблоны? – Jason

ответ

2

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

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

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

0

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

+0

есть ли какие-либо правила \ шаблоны, какие типы задач можно отменить, чего не может быть? – Jason

+0

Рекомендуемый способ - периодически проверять флаг внутри потока.Это действительно зависит от того, как вы на самом деле выполняете задание. Очевидно, это касается только потоков, которые могут выполняться вечно или в течение длительного времени. В других случаях лучше всего позволить потоку запускать и обрабатывать его, как только вы получите результат. Типичный случай, когда ваш контекст был уничтожен, но вы только что вернулись из потока. – breakline

0

Каждый поток имеет специальный флаг, который содержит состояние прерывания, доступ к нему осуществляется с помощью метода 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 
}