Насколько я понимаю, callable был добавлен в 1.5, а runnable интерфейс остался как есть, чтобы предотвратить конец света. Почему я не могу создать экземпляр ThreadPoolExecutor
(core, max, tu, unit, new BlockingQueue<Callable>())
- почему очередь обязательно берёт только runnable? Внутри, если бы я должен был отправить вызываемые вызовы, invokeAll, invokeAny, это должно быть хорошо, верно? Кроме того, будет shutDownNow()
< /a> вернуть список вызываемых объектов?
Почему я не могу создать экземпляр ThreadPoolExecutor с помощью BlockingQueue‹Callable›; почему только BlockingQueue‹Runnable›?
Ответы (3)
Вы можете отправить Callables
, но внутри они будут упакованы как Runnables
(фактически FutureTasks
, которые реализуют Runnable
). shutDownNow()
вернет только Runnables
, как написано на банке.
Если вы хотите получить список Callables
, которые не были запущены, вам нужно как-то отслеживать их самостоятельно (например, вести их список и возлагать на них ответственность за удаление себя из списка, когда они вызываются). .)
В качестве более общего ответа вы не можете повлиять на поведение программы Java во время выполнения, изменив параметр типа. Никакая ветвь if
не может быть перенаправлена на основе параметров типа. Если вы когда-нибудь окажетесь в ситуации, когда хотите получить другое поведение от API, никогда не ищите решение в выборе параметров типа.
В данном конкретном случае Runnable
является более общим типом объекта: это единица работы, которую внутренние компоненты Executor могут передать потоку. Например, Runnable
может содержать код, который вызывает Callable
и где-то сохраняет результат.
Он не может принимать как BlockingQueue<Callable<T>>
, так и BlockingQueue<Runnable>
из-за стирания типа; обе перегрузки будут иметь один и тот же необработанный тип BlockingQueue
и поэтому будут конфликтовать.
Однако я не знаю, что бы вы сделали со списком Callable
, отправленным исполнителю. Что бы вы сделали с их результатом? Куда это пойдет?
Похоже, вам нужен Future<T>
. Вы можете отправить коллекцию Callable<T>
, используя invokeAll
, и вы получите коллекцию Future<T>
, из которых вы сможете получить значения, как только они станут доступны.
List<Future<T>>
, полученные от invokeAll
, и проверить каждую на наличие isTerminate()
. Трудно дать более конкретный совет, не зная более подробно варианта использования.
- person yshavit; 09.08.2013
Runnable
s в очередьCallable
s. - person SLaks   schedule 09.08.2013