Почему я не могу создать экземпляр ThreadPoolExecutor с помощью BlockingQueue‹Callable›; почему только BlockingQueue‹Runnable›?

Насколько я понимаю, callable был добавлен в 1.5, а runnable интерфейс остался как есть, чтобы предотвратить конец света. Почему я не могу создать экземпляр ThreadPoolExecutor(core, max, tu, unit, new BlockingQueue<Callable>()) - почему очередь обязательно берёт только runnable? Внутри, если бы я должен был отправить вызываемые вызовы, invokeAll, invokeAny, это должно быть хорошо, верно? Кроме того, будет shutDownNow()< /a> вернуть список вызываемых объектов?


person foamroll    schedule 09.08.2013    source источник
comment
Потому что вы не можете добавить Runnables в очередь Callables.   -  person SLaks    schedule 09.08.2013


Ответы (3)


Вы можете отправить Callables, но внутри они будут упакованы как Runnables (фактически FutureTasks, которые реализуют Runnable). shutDownNow() вернет только Runnables, как написано на банке.

Если вы хотите получить список Callables, которые не были запущены, вам нужно как-то отслеживать их самостоятельно (например, вести их список и возлагать на них ответственность за удаление себя из списка, когда они вызываются). .)

person David Moles    schedule 09.08.2013

В качестве более общего ответа вы не можете повлиять на поведение программы Java во время выполнения, изменив параметр типа. Никакая ветвь if не может быть перенаправлена ​​на основе параметров типа. Если вы когда-нибудь окажетесь в ситуации, когда хотите получить другое поведение от API, никогда не ищите решение в выборе параметров типа.

В данном конкретном случае Runnable является более общим типом объекта: это единица работы, которую внутренние компоненты Executor могут передать потоку. Например, Runnable может содержать код, который вызывает Callable и где-то сохраняет результат.

person Marko Topolnik    schedule 09.08.2013
comment
Спасибо за руководство. Чтобы лучше понять, вы предлагаете мне использовать runnable, который обертывает вызываемый (который будет выдавать результаты где-то еще, кроме отправителя исходного runnable? как я могу получить это [должно быть много способов в зависимости от среды ] вообще? и эта способность читать результаты будет определять, что сработало, а что нет, что, я полагаю, более важно, хотя я все еще беспокоюсь о начале выполнения на этом этапе). - person foamroll; 09.08.2013
comment
Думаю, я понял, в чем заключается ваше замешательство: вы думаете, что переданная очередь является частью публичного API Executor, что-то, что вы сможете проверить на наличие содержимого во время работы Executor и т. д. Но на самом деле вы передаются в строительном блоке внутренних компонентов Executor, и причина, по которой конструктор принимает это, заключается в том, что особенности реализации очереди влияют на важные общие аспекты поведения Executor. Вы не должны каким-либо образом касаться этой очереди во время нормальной работы Executor. - person Marko Topolnik; 10.08.2013

Он не может принимать как BlockingQueue<Callable<T>>, так и BlockingQueue<Runnable> из-за стирания типа; обе перегрузки будут иметь один и тот же необработанный тип BlockingQueue и поэтому будут конфликтовать.

Однако я не знаю, что бы вы сделали со списком Callable, отправленным исполнителю. Что бы вы сделали с их результатом? Куда это пойдет?

Похоже, вам нужен Future<T> . Вы можете отправить коллекцию Callable<T>, используя invokeAll, и вы получите коллекцию Future<T>, из которых вы сможете получить значения, как только они станут доступны.

person yshavit    schedule 09.08.2013
comment
Ну, я хотел отслеживать, какие вызываемые объекты не выполнялись. Скажем, я отправляю/invokeAll/invokeAny список вызываемых объектов, и до того, как я смог перебрать все их future.get, или даже до того, как я смог начать итерацию, приложение закрывается, и мы выдаем ShutDownNow, могу ли я ожидать список из тех, которые даже не начали работать? Я полагаю, что ответ отрицательный, как указано @david-moles - person foamroll; 09.08.2013
comment
@SaadShakil Вы можете перебрать List<Future<T>>, полученные от invokeAll, и проверить каждую на наличие isTerminate(). Трудно дать более конкретный совет, не зная более подробно варианта использования. - person yshavit; 09.08.2013