Ответ 1
Прерывание вызовет поток из списка заданных условий ожидания. Ваш собственный флаг отмены не будет. Если вы хотите прервать ожидания в IO и событиях, используйте прерывание. В противном случае используйте свои собственные.
У меня длинная работа, что-то вроде:
public void myCancellableTask() {
while ( someCondition ) {
checkIfCancelRequested();
doSomeWork();
}
}
Задача может быть отменена (запрашивается отмена, а checkIfCancelRequested() проверяет флаг отмены). Обычно, когда я пишу обантурационные петли, как это, я использую флаг, указывающий, что запрос был отменен. Но, я знаю, я мог бы также использовать Thread.interrupt и проверить, был ли поток прерван. Я не уверен, какой был бы предпочтительный подход и почему, мысли?
спасибо,
Джефф
Прерывание вызовет поток из списка заданных условий ожидания. Ваш собственный флаг отмены не будет. Если вы хотите прервать ожидания в IO и событиях, используйте прерывание. В противном случае используйте свои собственные.
Одна из проблем с использованием прерывания заключается в том, что если вы не контролируете весь выполняемый код, вы рискуете, что прерывание не будет работать "должным образом" из-за того, что кто-то еще не понимает, как обрабатывать прерывания в их библиотеке. Это API, который невидимо экспортирует API вокруг обработки interrupt
, от которого вы зависите.
В вашем примере предположим, что doSomeWork
был в стороннем JAR и выглядит так:
public void doSomeWork() {
try {
api.callAndWaitAnswer() ;
}
catch (InterruptedException e) { throw new AssertionError(); }
}
Теперь вам нужно обработать AssertionError
(или что-нибудь еще, что может использовать библиотека, которую вы используете). Я видел, как опытные разработчики бросают всякие глупости на получение прерываний! С другой стороны, возможно, метод выглядел так:
public void doSomeWork() {
while (true) {
try {
return api.callAndWaitAnswer() ;
}
catch (InterruptedException e) { /* retry! */ }
}
}
Эта "неправильная обработка" прерывания заставляет вашу программу зацикливаться на неопределенный срок. Опять же, не отвергайте это как смешное; там много механизмов прерывания обработки прерываний.
По крайней мере, использование вашего собственного флага будет полностью невидимым для любых сторонних библиотек.
Это зависит от реализации doSomeWork()
. Является ли это чистое вычисление или оно (в любой момент) связано с блокированием API (например, IO)? В ответе на bmargulies многие блокирующие API в JDK прерываются и будут распространять прерванное исключение на стек.
Итак, если работа влечет за собой потенциально блокирующие действия, вам нужно принять во внимание прерывания, даже если вы решите управлять процессом с использованием флага и должны соответствующим образом уловить и обработать/развернуть прерывания.
Кроме того, если вы полагаетесь на флаг, убедитесь, что ваш флаг объявлен семантикой volatile
.
Я думаю, что это вопрос предпочтения в большинстве случаев. Лично я бы пошел за ручным флагом. Это дает вам больше контроля - например, таким образом вы убедитесь, что ваш поток не оставляет какой-либо другой объект в несогласованном состоянии. Кроме того, если производительность действительно важна, помните, что использование исключений имеет накладные расходы (даже если это незначительно в 99% случаев).