Синхронизация пула потоков Java

Я хотел бы выполнить следующий алгоритм - это должно быть сделано на Java

for(int i = 0; i< 100; i++){
    create 8 threads which perform a task
    wait for all threads to finish
}

Желательно, чтобы потоки не создавались и не уничтожались постоянно из-за накладных расходов (и того факта, что каждый поток будет иметь ‹20 миллисекунд работы), что привело к идее пулов потоков1. Я также знаю, что с помощью Executable2 , можно вызвать shutdown, а затем awaitTermination. Однако в данном случае это нежелательно из-за петли. Таким образом, как может происходить синхронизация потоков?

Я хотел бы синхронизировать потоки в пуле потоков, как это было бы сделано с использованием метода join() традиционного потока.


person ET13    schedule 29.11.2011    source источник
comment
Вопрос не ясен. Вы создаете 100 раз 8 потоков или обрабатываете 100 задач в 8 потоков? Что вам нужно для синхронизации (вы синхронизируете данные, а не потоки)?   -  person toto2    schedule 29.11.2011
comment
Вы уверены, что вам нужно дождаться завершения всех 8 задач, прежде чем начинать новую задачу? Если вам нужно 8 потоков, потому что у вас есть 8-ядерная машина, вам просто нужно использовать 8-поточный ThreadPool.   -  person toto2    schedule 30.11.2011


Ответы (3)


Пробовали ли вы смотреть на циклический барьер< /а>. Он оптимизирован, чтобы позволить группе потоков останавливаться и ждать, пока все не достигнут общего барьера. Я не вижу причин, по которым его нельзя использовать с известным количеством потоков в пуле со ссылками на общий барьер. Могут быть некоторые дополнительные сложности, если вам нужно синхронизировать обратный вызов, вызванный с барьерами await() count, поскольку он выполняется в другом потоке.

person nsfyn55    schedule 29.11.2011
comment
Спасибо, это выглядит очень полезным. Я попытаюсь связать циклический барьер с пулами потоков и опубликую свои результаты. Однако я хочу указать, что вы ошибаетесь, полагая, что меня интересует функциональность, у меня просто есть приложение, которое я хотел бы ускорить с помощью потоковой передачи, которая требует синхронизации. - person ET13; 30.11.2011

Вам нужно поместить все свои задачи в очередь, а затем передать эту очередь ThreadPoolExecutor. Вы сообщаете исполнителю пула потоков, сколько потоков использовать, и он позаботится о выполнении задач.

person TMN    schedule 29.11.2011
comment
Однако это не решает проблему синхронизации, если я не ошибаюсь? - person ET13; 30.11.2011
comment
Если вам это действительно нужно (и если да, то почему ваш список задач не кратен 8?), вы можете поставить задачи в очередь задач по 8 за раз и переопределить ThreadPoolExecutor.afterExecute(), чтобы проверить, все ли задачи выполнены, и, если да, добавить еще 8 в очередь. - person TMN; 30.11.2011

Взгляните на структуру fork/join jdk 7.

person Puce    schedule 29.11.2011
comment
Спасибо, я уже читал о Fork/Join Framework здесь (docs .oracle.com/javase/tutorial/essential/concurrency/), но его отговорили от его использования, поскольку он предназначен для рекурсивных алгоритмов, в то время как алгоритм, который я пытаюсь реализовать, гораздо проще реализовать итеративно. Кроме того, у меня есть фиксированное количество потоков, в которых я хотел бы, чтобы это выполнялось, в то время как этот алгоритм лучше подходит для разделения задачи на небольшие единицы работы и позволяет Fork/Join выяснить, как лучше всего использовать ресурсы соответственно. - person ET13; 30.11.2011