Рубрики

Java.util.concurrent.CyclicBarrier в Java

CyclicBarrier используется, чтобы заставить потоки ждать друг друга. Он используется, когда разные потоки обрабатывают часть вычислений и когда все потоки завершили выполнение, результат необходимо объединить в родительский поток. Другими словами, CyclicBarrier используется, когда несколько потоков выполняют разные подзадачи, и выходные данные этих подзадач должны быть объединены для формирования окончательного результата. После завершения его выполнения потоки вызывают метод await () и ждут, пока другие потоки достигнут барьера. Как только все потоки достигнуты, барьеры дают путь для продолжения потоков.

Работа CyclicBarrier

CyclicBarriers определены в пакете java.util.concurrent. Сначала создается новый экземпляр CyclicBarriers, определяющий количество потоков, которые должны ожидать барьеры.

CyclicBarrier newBarrier = new CyclicBarrier(numberOfThreads);

Каждый поток выполняет некоторые вычисления и после завершения своего выполнения вызывает методы await (), как показано ниже:

public void run()
{
    // thread does the computation
    newBarrier.await();
}

Работа CyclicBarrier:

Как только число потоков, вызвавших await (), равно numberOfThreads , барьер дает путь ожидающим потокам. CyclicBarrier также может быть инициализирован некоторым действием, которое выполняется, как только все потоки достигли барьера. Это действие может комбинировать / использовать результат вычисления отдельного потока, ожидающего в барьере.

Runnable action = ... 
//action to be performed when all threads reach the barrier;
CyclicBarrier newBarrier = new CyclicBarrier(numberOfThreads, action);

Важные методы CyclicBarrier:

  1. getParties: возвращает количество сторон, необходимое для преодоления этого барьера.
    Синтаксис:
    public int getParties()

    Возвращает:
    количество сторон, необходимых для преодоления этого барьера

  2. Сброс: Сбрасывает барьер в исходное состояние.
    Синтаксис:
    public void reset()

    Возвращает:
    void, но сбрасывает барьер до исходного состояния. Если какие-либо стороны в настоящее время ждут у барьера, они вернутся с BrokenBarrierException.

  3. isBroken: Запрашивает, находится ли этот барьер в поврежденном состоянии.
    Синтаксис:
    public boolean isBroken()

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

  4. getNumberWaiting: Возвращает количество сторон, ожидающих в данный момент на барьере.
    Синтаксис:
    public int getNumberWaiting()

    Возвращает:
    количество сторон, в настоящее время заблокированных в ожидании ()

  5. await: ждет, пока все стороны будут задействованы, ожидает этого барьера.
    Синтаксис:
    public int await() throws InterruptedException, BrokenBarrierException

    Возвращает:
    индекс прибытия текущего потока, где индекс getParties () — 1 указывает на первое прибытие, а ноль указывает на последнее прибытие.

  6. await: ожидание, пока все стороны вызвали ожидание этого барьера, или пока не истечет указанное время ожидания.
    Синтаксис:
    public int await(long timeout, TimeUnit unit) 
    throws InterruptedException,
    BrokenBarrierException, TimeoutException

    Возвращает:
    индекс прибытия текущего потока, где индекс getParties () — 1 указывает на первое прибытие, а ноль указывает на последнее прибытие

// JAVA-программа для демонстрации выполнения на циклическом барьере

  

import java.util.concurrent.TimeUnit;

import java.util.concurrent.TimeoutException;

import java.util.concurrent.BrokenBarrierException;

import java.util.concurrent.CyclicBarrier;

  

class Computation1 implements Runnable

{

    public static int product = 0;

    public void run()

    {

        product = 2 * 3;

        try

        {

            Tester.newBarrier.await();

        

        catch (InterruptedException | BrokenBarrierException e) 

        {

            e.printStackTrace();

        }

    }

}

  

class Computation2 implements Runnable

{

    public static int sum = 0;

    public void run()

    {

        // проверяем, сломан newBarrier или нет

        System.out.println("Is the barrier broken? - " + Tester.newBarrier.isBroken());

        sum = 10 + 20;

        try

        {

            Tester.newBarrier.await(3000, TimeUnit.MILLISECONDS);

          

            // количество сторон, ожидающих у барьера

            System.out.println("Number of parties waiting at the barrier "+

            "at this point = " + Tester.newBarrier.getNumberWaiting());

        

        catch (InterruptedException | BrokenBarrierException e) 

        {

            e.printStackTrace();

        

        catch (TimeoutException e) 

        {

            e.printStackTrace();

        }

    }

}

  

  

public class Tester implements Runnable

{

    public static CyclicBarrier newBarrier = new CyclicBarrier(3);

      

    public static void main(String[] args)

    {

        // родительский поток

        Tester test = new Tester();

          

        Thread t1 = new Thread(test);

        t1.start();

    }

    public void run()

    {

        System.out.println("Number of parties required to trip the barrier = "+

        newBarrier.getParties());

        System.out.println("Sum of product and sum = " + (Computation1.product + 

        Computation2.sum));

          

        // объекты, на которых должен выполняться дочерний поток

        Computation1 comp1 = new Computation1();

        Computation2 comp2 = new Computation2();

          

        // создание дочернего потока

        Thread t1 = new Thread(comp1);

        Thread t2 = new Thread(comp2);

          

        // перевод дочернего потока в работоспособное состояние

        t1.start();

        t2.start();

  

        try

        {

            Tester.newBarrier.await();

        

        catch (InterruptedException | BrokenBarrierException e) 

        {

            e.printStackTrace();

        }

          

        // барьер разрывается как номер потока, ожидающего барьер

        // в этот момент = 3

        System.out.println("Sum of product and sum = " + (Computation1.product + 

        Computation2.sum));

                  

        // Сброс newBarrier

        newBarrier.reset();

        System.out.println("Barrier reset successful");

    }

}

Выход:

<Number of parties required to trip the barrier = 3
Sum of product and sum = 0
Is the barrier broken? - false
Number of parties waiting at the barrier at this point = 0
Sum of product and sum = 36
Barrier reset successful

Объяснение: Значение (sum + product) = 0 выводится на консоль, поскольку дочерний поток еще не запущен для установки значений sum и переменной product. После этого (sum + product) = 36 выводится на консоль, потому что дочерние потоки запустили установку значений sum и product. Кроме того, количество ожидающих нитей на барьере достигло 3, благодаря чему барьер затем позволил всем нитям пройти и, наконец, 36 был напечатан. Значение «Число сторон, ожидающих у барьера в этой точке» = 0, потому что все три потока уже вызвали метод await () и, следовательно, барьер больше не активен. В конце newBarrier сбрасывается и может использоваться снова.

BrokenBarrierException

Барьер ломается, когда любая из ожидающих нитей покидает барьер. Это происходит, когда один или несколько ожидающих потоков прерываются или когда время ожидания истекло, поскольку поток вызвал методы await () со следующим временем ожидания:

newBarrier.await(1000, TimeUnit.MILLISECONDS);
// thread calling this await() 
// methods waits for only 1000 milliseconds.

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

Разница между CyclicBarrier и CountDownLatch

  • CountDownLatch может использоваться только один раз в программе (пока его количество не достигнет 0).
  • CyclicBarrier может использоваться снова и снова, как только все потоки в барьерах освобождаются.

Ссылка: Oracle

Эта статья предоставлена Mayank Kumar . Если вы как GeeksforGeeks и хотели бы внести свой вклад, вы также можете написать статью с помощью contribute.geeksforgeeks.org или по почте статьи contribute@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Рекомендуемые посты:

Java.util.concurrent.CyclicBarrier в Java

0.00 (0%) 0 votes