Cancel() vs remove() для исполнителей

Недавно я работал с ThreadPoolExecutor и priorityqueue и столкнулся с обоими методами future.cancel() для будущей задачи. И task.remove() для самой задачи, чтобы удалить ее из очереди.

Какой вариант лучше? есть ли разница? Я могу сохранить список обоих (будущий объект, полученный от submit(), или сами задачи), не знаю, что использовать...

удалять:

executor.remove(task);
executor.purge();

Отмена:

futureObject.cancel(false);

Я использовал следующее: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html#remove%28java.lang.Runnable%29

Ложь в отмене заключается в том, что я хочу удалить только задачу очереди, если она выполняется, пусть она завершится.


person sharon gur    schedule 02.06.2015    source источник


Ответы (3)


Используйте 1_

В Javadoc для ThreadPoolExecutor.remove() говорится, что он может «не удалить задачи, которые были преобразованы в другие формы перед помещением во внутреннюю очередь», поэтому я бы не рекомендовал вызывать его, если вы не уверены, что задача не была преобразована внутри.

Учитывая это, если у вас есть Future, я бы порекомендовал отменить его, позвонив в Future.cancel(). У этого есть дополнительное преимущество: делать правильные вещи, если кто-то еще имеет ссылку на Future и решает вызвать Future.get().

Если вы параноидально относитесь к объему кучи, используемому отмененными задачами, вы можете вызвать ThreadPoolExecutor.purge() после вызова Future.cancel().

Кстати, метод ThreadPoolExecutor.purge() удаляет только фьючерсы, которые были отменены, поэтому вызов purge() после remove(), скорее всего, не будет работать.

person NamshubWriter    schedule 03.06.2015

Я бы использовал тот, который более естественен для вас. Без дополнительной информации это, скорее всего, cancel

remove/purge намного дороже и действительно нужен только в том случае, если вы обеспокоены тем, что у вас будет так много таких задач, что они могут использовать слишком много памяти.

Разница довольно очевидна, отмена просто отменяет задачу. remove/purge удаляет задачу из очереди.

person Peter Lawrey    schedule 02.06.2015
comment
Я использую priorityQueue, поэтому я сохраняю ComparableFutureTask, как это предполагает: com/questions/30574777/ Я переопределяю выполнение, чтобы вернуть эту ComparabaleFutureTask, и сохраняю все ссылки, и для этого объекта я предварительно формирую cancel(). и по какой-то причине это не работает ... Я предполагаю, что мне нужно открыть новый вопрос, специфичный для этого случая, но предполагается ли, что он будет работать так же на сравнимой FutureTask? Любой - person sharon gur; 03.06.2015
comment
@sharongur, что ты имеешь в виду; это не работает, и что вы ожидали, что произойдет? - person Peter Lawrey; 03.06.2015
comment
Я отменяю задачу и заново вставляю новую с более высоким приоритетом, но порядок выполнения остается прежним. а новая задача не вставлена - person sharon gur; 03.06.2015
comment
@sharongur, значит, проблема в том, что вставки не отменяются и не удаляются? Т.е. не относящийся к вопросу? - person Peter Lawrey; 03.06.2015
comment
На самом деле я сделал именно то, что предлагает вопрос, который я разместил, но когда я добавил cancel(); Я не видел никакой разницы с тем, когда я не инициировал тот же метод. Во всяком случае, я недостаточно исследовал это, чтобы поднять другой вопрос. Я попытаюсь решить это сам, и если я не найду решения, я снова появлюсь здесь :) спасибо за помощь! - person sharon gur; 03.06.2015
comment
Отмена @sharongur просто помечает задачу как отмененную и не запускается. Он делает это, потому что это более эффективно, чем удаление его из структуры данных. Однако иногда вы действительно хотите, чтобы он исчез, поэтому есть возможность удалить его, хотя в некоторых случаях это происходит медленнее, намного медленнее. - person Peter Lawrey; 03.06.2015

Если вы ожидаете, что cancel будет переопределено, или вас больше всего беспокоит объем памяти, используйте remove/purge. Но в любом другом случае я бы выбрал cancel.

person JiriS    schedule 02.06.2015