Параллелизм - прерывание будущего без его отмены

Есть ли способ прервать будущее, не отменяя его?

java doc API:

логическое отмена (логическое mayInterruptIfRunning)

Пытается отменить выполнение этой задачи. Эта попытка не удастся, если задача уже завершена, уже отменена или не может быть отменена по какой-либо другой причине. В случае успеха, и эта задача не была запущена при вызове отмены, эта задача никогда не должна запускаться. Если задача уже запущена, то параметр mayInterruptIfRunning определяет, следует ли прервать поток, выполняющий эту задачу, при попытке остановить задачу.

Чтобы перехватить прерывание, мы должны правильно перехватить прерванное исключение или проверить метод isInterrupted () в методе Runnable / Callable.

Но нет возможности прервать работу Future с помощью интерфейса Future.

Поскольку все потоки находятся в пуле службы исполнителя, никто не может выполнять thread.interrupt (). Поэтому предполагалось, что любое прерывание произойдет только тогда, когда Future отменяется или пул потоков завершается?

Я пытаюсь понять, почему в интерфейсе Future нет метода прерывания. Любая помощь будет оценена


person AKSG    schedule 17.01.2012    source источник
comment
Интересно, какой в ​​этом смысл ... это интересный, если не странный, вопрос.   -  person    schedule 18.01.2012
comment
Из-за нескольких проблем. 1.) прерывание - это риск, вы никогда не знаете, когда или когда задача может быть прервана, 2.) будущее не привязано ни к какому потоку. Прерывание потока Future может привести к поломке других Futures, 3.) Используя механизм отмены, вы избегаете одной из наиболее распространенных ловушек, связанных с гонками и взаимоблокировкой, 4.) вы получаете высокую гарантию того, что ваш код не будет остановлен случайным образом. государство.   -  person Rekin    schedule 18.01.2012
comment
Будущее представляет собой результат асинхронных вычислений - разве не было бы опасно прервать асинхронный объект, поскольку вызывающий поток может продолжать работать и ожидает ответа от асинхронного объекта?   -  person Zack Macomber    schedule 18.01.2012
comment
@Rekin: Звучит как хороший ответ для меня.   -  person skaffman    schedule 18.01.2012
comment
@Rekin: Я согласен со skaffman - почему бы не поставить свой комментарий в качестве ответа?   -  person Zack Macomber    schedule 18.01.2012
comment
Зачем вам прерывать задачу, если не отменять ее?   -  person jtahlborn    schedule 18.01.2012
comment
@Rekin - не совсем согласен с вашим ответом. метод Future.cancel() действительно использует Thread.interrupt() под капотом, поэтому я не понимаю вашу попытку различить 2. вы путаете Thread.interrupt() с Thread.stop()?   -  person jtahlborn    schedule 18.01.2012
comment
Похоже, фреймворк ожидает, что Futures предоставит результат после асинхронных вычислений - и это нормально. Но плохая сторона в том, что нет умного способа прервать поток. Причина, по которой я говорю это, состоит в том, что мы прерываем нить, когда отменяем будущее. В этом случае прерывание переходит к потоку, только если поток работает. Но я полагаю, что параллелизм - это очень деликатный фреймворк, с которым нужно обращаться очень осторожно - так что я думаю, что на запрос был дан ответ :) Спасибо за помощь! Я могу отметить это как ответ   -  person AKSG    schedule 18.01.2012
comment
В настоящее время прервать будущее = остановить его. Я бы сказал, что если бы была возможность прервать Future, то на основе прерывания Future могло бы выполнять некоторые другие действия, а затем, если требуется, может вернуться к исходному действию, которое оно выполняло. Но я также понимаю вашу точку зрения - в цикле Future может проверять какой-то другой флаг и выполнять другую работу на основе этого флага. Я также согласен с тем, что прерывание может означать, что поток может быть остановлен в произвольном состоянии. Но разве это не решать разработчикам?   -  person AKSG    schedule 18.01.2012
comment
@jtahlborn: Да, я перепутал этих двоих. Итак, правильным комментарием будет: создайте свой собственный механизм остановки поверх _1 _ / _ 2_ вместо использования опасного Thread.stop() метода, который может вызвать очень неожиданные побочные эффекты. Спасибо! :)   -  person Rekin    schedule 18.01.2012
comment
@AKSG: Да, но разработчики фреймворка параллелизма уже решили, так что он вроде встроен. Но представьте, если бы каждый Future запускал и просматривал новый поток. Затем вы можете ответить на нормальный флаг прерывания, остановив второй поток. Таким извращенным способом вы могли вернуть управление в настройках Future. Я здесь не спорю, хорошо это или плохо, я только показываю, что это возможно.   -  person Rekin    schedule 18.01.2012
comment
Одна из причин прерывать будущее - сообщить ему, что произошло какое-то событие, на основании которого будущему нужно что-то сделать. Но в момент прерывания, если будущее не запущено или будущее уже завершено - тогда это проблема. Таким образом, похоже, что если будущее действительно нужно уведомить о событии, оно должно ждать состояния блокировки (кто-то может сигнализировать об этом). Прерывание на будущее означает его отмену. Кроме того, тот факт, что прерывание ВСЕГДА означает отмену, упрощает обработку прерывания в исполняемом коде. Теперь это становится ясным :)   -  person AKSG    schedule 19.01.2012
comment
@AKSG: Лучшим источником информации по этой теме, вероятно, является книга Джошуа Блоха «Параллелизм Java на практике». Для меня это лучшая книга по Java, которую я когда-либо читал.   -  person Rekin    schedule 19.01.2012
comment
stackoverflow.com/ questions / 3522427 /   -  person kervin    schedule 30.01.2016


Ответы (3)


Причина в том, что абстракция Future отличается от конкретного исполнения в потоке. Мы не можем сказать, привязано ли будущее к одному или нескольким потокам. Будущее может запускать новые потоки, запускать новые фьючерсы и т. Д.

Рассматривайте эти абстракции как взаимодействия между клиентским кодом и исполнителем фьючерсов. Концептуально имеет смысл сказать «отмените эту задачу, которую я просил вас выполнить», потому что это была ваша задача отменить. Я могу быть занят, работая над этим, или я, возможно, еще не начал, или он может быть закончен, но все в порядке, я отменю его, если вы хотите, чтобы я это сделал. Вот почему у нас есть метод отмены.

С другой стороны, не имеет большого смысла говорить «прервать вашу задачу». Из-за разделения между результатом действия (Будущее) и моделью выполнения (скажем, Исполнитель) клиент не знает, какие действия предпринимаются для выполнения задачи. Как тогда можно ожидать, что клиент узнает, когда прерывание уместно, требуется или даже поддерживается.

person sksamuel    schedule 22.01.2012
comment
docs.oracle.com/javase/tutorial/essential/concurrency/ - Прерывание - это указание потоку, что он должен остановить то, что он делает, и сделать что-то еще. Программист должен решить, как именно поток реагирует на прерывание, но очень часто поток завершается. Но в случае с Будущим прерывание означает прекращение. Я согласен с тем, что все, что можно сделать с помощью прерывания, Будущее должно будет сделать это само - как ожидание условия. Но я не согласен с тем, что прерывать будущее не имеет смысла - хотя сложности могут и не стоить - person AKSG; 23.01.2012

В любом случае вы можете использовать тайм-аут, чтобы прервать ожидание.

get(long timeout, TimeUnit unit) 
person Dimitri    schedule 01.02.2012
comment
Вы действительно прерываете ожидание в вызывающем потоке, но нет логики выполнения потока для получения результата от Future. Есть интересная проблема кодирования: семантика частичных результатов передается прерывающему потоку, чтобы получить частичный результат. - person Bartosz Bilicki; 25.05.2014

Для этого есть полезные варианты использования.

Поскольку проблема с Future API заключается в том, что он не предоставляет возможности обнаруживать остановку выполнения. Оба isCancelled () и isDone () с радостью вернут истину, даже если выполнение Callable продолжается.

Так что на данном этапе дело не в уровне абстракции API Future. Но это неспособность определить завершение задачи. Иными словами, невозможно различить запрос на отмену и завершенное действие отмены.

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

person kervin    schedule 30.01.2016