2013-08-09 3 views
3

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

+0

Потому что вы не можете добавить 'Runnable' в очередь 'Callable'. – SLaks

ответ

7

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

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

2

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

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

+0

Спасибо за руководство. Чтобы лучше понять, вы предполагаете, что я использую runnable, который обертывает вызываемый (который будет выплевывать результаты где-то в другом месте, кроме отправителя исходного runnable? Как я могу это сделать? [Должно быть много способов в зависимости от среды ] в целом? и эта способность читать результаты определит, что сработало, а не, что, на мой взгляд, более важно, хотя я все равно обеспокоен началом выполнения на этом этапе). – Saad

+0

Я думаю, что я понял, в чем заключается ваша путаница: вы считаете, что переданная очередь является частью публичного API-интерфейса Executor, что вы сможете проверить на содержимое, пока выполняется Исполнитель, и т. Д. Но на самом деле вы проходите в строительном блоке внутренних органов Исполнителя, и причина, по которой конструктор соглашается с этим, заключается в том, что особенности реализации очереди влияют на важные общие аспекты поведения Исполнителя. Вы * не * должны касаться этой очереди каким-либо образом во время нормальной работы Executor. –

1

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

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

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

+0

Ну, я хотел отслеживать, какие вызовы не выполнялись. Скажем, я отправляю/invokeAll/invokeAny список вызываемых вызовов, и до того, как я смог выполнить итерацию по всему их будущему. Или даже до того, как я смог начать выполнять итерацию, приложение отключается, и мы выдаем shutDownNow, могу ли я ожидать список из тех, которые даже не начали работать?Я полагаю, что ответ отрицательный, как описано @ david-moles. – Saad

+1

@SaadShakil. Вы можете выполнить итерацию через 'List >' s, который вы получили из 'invokeAll', и проверить каждый для' isTerminate() '. Трудно дать более конкретный совет, не зная случая использования более подробно. – yshavit