Как получить доступ к основной очереди ThreadpoolExecutor потокобезопасным способом - PullRequest
0 голосов
/ 09 мая 2011

Метод getQueue () обеспечивает доступ к базовой очереди блокировки в ThreadPoolExecutor, но это не кажется безопасным.

Обход в очереди, возвращенной этой функцией, может пропустить обновления, внесенные в очередь ThreadPoolExecutor.

"Метод getQueue () разрешает доступ к рабочей очереди для целей мониторинга и отладки. Использование этого метода для любых других целей настоятельно не рекомендуется."

Что бы вы сделали, если бы хотели пересмотреть workQueue, используемый ThreadPoolExecutor? Или есть альтернативный подход?

Это продолжение .. Выбор структуры данных для варианта задачи потребителя производителя

Теперь я пытаюсь использовать несколько производителей для нескольких потребителей, но я хочу использовать некоторый существующий пул потоков, поскольку я не хочу сам управлять пулом потоков, а также я хочу получить обратный вызов, когда ThreadPoolExecutor завершил выполнение некоторой задачи вместе с возможность проверять потокобезопасным способом структуру данных "транзакции в процессе".

Ответы [ 3 ]

1 голос
/ 20 мая 2011

Если вы хотите скопировать элементы в очереди и убедиться, что то, что у вас в очереди, не было выполнено, вы можете попробовать это:

a) Ввести возможность приостановить и возобновить выполнение.См .: http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ThreadPoolExecutor.html

b) сначала сделайте паузу в очереди, затем скопируйте очередь, затем возобновите очередь.

И затем у меня возник вопрос.Проблема, которую я вижу, заключается в том, что пока вы выполняете свой «Runnable», этот «Runnable» не помещается в очередь, а является «оболочкой» FutureTask, и я не могу найти какой-либо способ определить, какой из моих runnables я ищув.Таким образом, захват и изучение очереди довольно бесполезны.Кто-нибудь знает, что я там пропустил?

1 голос
/ 09 мая 2011

Вы можете переопределить методы beforeExecute и afterExecute, чтобы сообщить, что задача запущена и завершена. Вы можете переопределить execute (), чтобы знать, когда добавляется задача.

Проблема, с которой вы столкнулись, заключается в том, что очередь не предназначена для запроса, и задание может быть использовано до того, как вы его увидите. Одним из способов решения этой проблемы является создание собственной реализации очереди (возможно, переопределение / обертывание ConcurrentLinkedQueue)

Кстати: очередь является поточно-ориентированной, однако не гарантируется, что вы увидите каждую запись.

ConcurrentLinkedQueue.iterator () задокументирован как

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

0 голосов
/ 09 мая 2011

Если вы следуете совету Джона Скита в своем принятом ответе из предыдущего вопроса, то вы будете контролировать доступ к своим очередям с помощью блокировок. Если вы получите блокировку в очереди в процессе, вы можете гарантировать, что при обходе не пропустит ни одного элемента в ней.

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

...