Многопоточность. Класс CyclicBarrier

В многопоточном программировании часто случаются ситуации, когда поток должен находится в режиме ожидания в определенной точке приложения, пока остальные потоки не достигнут этой точки. Как только нужное количество потоков достигает точки ожидания, то приостановка выполнения потоков снимается и потоки могут вновь продолжить свою работу. На пример, если ряд потоков, каждый из которых выполняет часть общего вычисления и результат их работы должен быть объединен в общий результат. Объединить результат вычисления можно только в том случае, когда все потоки завершат свои маленькие вычисления. Поэтому потоки, которые первые завершили свою работы должны ожидать завершения работы оставшихся потоков. Для реализации описанного механизма в пакете java.util.concurrent предусмотрен класс CyclicBarrier (с версии 1.5).

Класс CyclicBarrier

Для создания экземпляра класса CyclicBarrier предусмотрено два конструктора. Первый конструктор принимает в качестве параметра — количество потоков которое нужно достигнуть для снятия барьера:

Второй конструктор принимает количество потоков и поток вида Runnable, который будет запущен по достижении барьера указанным в первом параметре количеством потоков:

Когда поток достигает барьера нужно вызвать метод await класса CyclicBarrier. В результате выполнения метода await работа потока приостанавливается до того момента пока указанное нами количество потоков не вызовет метод await и барьер не будет снят.
В классе CyclicBarrier представлено две формы метода await. В первой форме ожидание снятия барьера длится без ограничения по времени:

Во второй же форме указывается ограничение по времени, по истечении которого барьер будет снят:

Время ожидания указывается в формате TimeUnit.
После того как барьер будет снят и все потоки освобождены, барьер можно будет использовать повторно, в этом его принципиальное отличие от класса CountDownLatch, который мы рассматривали ранее.

Пример

Возможный результат выполнения:

В теле метода main() создается барьер с ожиданием 5 потоков и указывается поток который должен быть выполнен по достижению барьера. Далее запускаются 5 потоков. Потоки, которые будут ждать снятия барьера представлены классом CustomThread, в конструкторе которого происходит непосредственно запуск потока, а в методе run() происходит вызов ожидания снятия барьера с обязательным перехватом исключений. Поток, который будет выполнен в результате снятия барьера представлен классом Action и состоит всего из одного метода run().

Исходный код доступен на GitHub

Site Footer