Примеры из реальной жизни для CountDownLatch и CyclicBarrier

Убедитесь, что вы воспринимаете производительность .

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

  1. индикаторы выполнения, которые плавно продвигались к завершению
  2. индикаторы выполнения, которые ускорялись к концу
BLOCKQUOTE>

23
задан trashgod 14 April 2012 в 18:57
поделиться

9 ответов

Ключевое отличие состоит в том, что CountDownLatch разделяет потоки на официантов и поступающих, тогда как все потоки, использующие CyclicBarrier, выполняют обе роли.

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

Ваш пример защелки подразумевает, что все десять человек должны подождать, чтобы поднять камень вместе. Это не вариант. Лучшим примером из реальной жизни был бы подсказчик для экзамена, который терпеливо ждет, когда каждый студент сдаст свой тест. Студенты не ждут, когда они закончат свои экзамены и могут свободно уйти. Когда последний учащийся сдает экзамен (или истекает срок), суфлер перестает ждать и уходит с тестами.

36
ответ дан David Harkness 14 April 2012 в 18:57
поделиться

В гипотетическом театре,

он называется Мьютекс , если только один человек позволяет смотреть пьесу
, он называется Семафор , если Количество зрителей позволяет смотреть спектакль. Если кто-либо покинет Театр во время спектакля, то другой человек может посмотреть спектакль.
он называется CountDownLatch , если никто не имеет права входить до тех пор, пока каждый человек не покинет театр. У каждого человека есть свобода воли покинуть театр.
это называется Cyclicbarrier , если театр не запустится, пока каждый человек не войдет в театр. Здесь шоумен не может начать шоу, пока все люди не войдут и не схватят место. Как только воспроизведение закончится, тот же барьер будет применяться для следующего шоу

Здесь человек - это Нить, игра - это ресурс.

40
ответ дан Shailesh kumar 14 April 2012 в 18:57
поделиться

Пример из реального мира Я вижу, что на самом деле во всех ответах отсутствует реальный пример. Как и в том, как эти классы могут быть использованы в программной сфере

  1. CountDownLatch Многопоточный менеджер загрузок. Диспетчер загрузки запустит несколько потоков для одновременной загрузки каждой части файла (при условии, что сервер поддерживает загрузку нескольких потоков). Здесь каждый поток будет вызывать метод обратного отсчета экземпляра защелки. После того как все потоки закончили выполнение, поток, связанный с защелкой обратного отсчета, объединит детали, найденные в разных частях, в один файл

  2. CyclicBarrier Тот же сценарий, что и выше .. Но предположим, что файлы загружаются из P2P. Снова несколько потоков, загружающих части. Но здесь, предположим, что вы хотите, чтобы проверка целостности загруженных фрагментов выполнялась через определенный промежуток времени. Здесь циклический барьер играет важную роль. После каждого временного интервала каждый поток будет ждать у барьера, чтобы поток, связанный с циклическим барьером, мог выполнить проверку целостности. Эта проверка целостности может выполняться несколько раз благодаря CyclicBarrier

Пожалуйста, исправьте меня, если что-то не так.

12
ответ дан FatherMathew 14 April 2012 в 18:57
поделиться

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

4
ответ дан trashgod 14 April 2012 в 18:57
поделиться

Вариант использования 1 Предположим, что вы разбили большое задание на 10 небольших заданий, каждое из которых представляет собой поток. Вы должны дождаться окончания 10 задач из этих потоков, прежде чем считать выполненную работу.

Таким образом, основной поток инициатора задания инициализирует CountDownLatch числом используемых потоков, он распределяет задачи по потокам и ожидает, пока защелка не поднимется до нуля с помощью метода await. Каждый поток исполнителя будет вызывать countDown в конце своей задачи. Наконец, основной поток будет пробужден после завершения всех потоков, поэтому он считает, что вся работа выполнена. В этом сценарии используется защелка doneSignal, описанная в javadoc CountDownLatch.

Вариант использования 2 Предположим, вы разбили большую работу на n * m задач, распределенных по n потокам. m соответствует строке матрицы, и у вас есть общее количество для каждой строки. В этом случае потоки должны быть синхронизированы после завершения каждой задачи, чтобы вычислить общее значение для строки. В этом случае CyclicBarrier, инициализированный числом потоков n, используется для ожидания конца вычисления каждой строки (фактически m раз).

Чтобы сравнить оба, предполагается, что CountDownLatch будет использоваться только 1 раз, а CyclicBarrier может использоваться столько раз, сколько алгоритму требуется точка синхронизации для набора потоков.

4
ответ дан Yves Martin 14 April 2012 в 18:57
поделиться

Теоретическая разница:

В CountDownLatch основные потоки ожидают, пока другие потоки завершат свое выполнение. В CyclicBarrier рабочие потоки ждут друг друга, чтобы завершить свое выполнение.

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

Пример из реальной жизни: -

CountDownLatch: Рассмотрим сценарий мира ИТ, в котором менеджер разделил модули между группами разработчиков (А и В) и хочет, чтобы назначьте его команде QA для тестирования, только когда обе команды выполнят свою задачу.

Здесь поток менеджера работает как основной поток, а команда разработчиков работает как рабочий поток. Поток менеджера ожидает, пока поток команды разработчиков завершит свою задачу.

CyclicBarrier: Рассмотрим тот же сценарий мира ИТ, в котором менеджер разделил модули между группами разработчиков (А и В). Он уходит в отпуск и просит обе команды подождать, пока они выполнят свою задачу, после того как обе команды назначат ее для тестирования.

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

3
ответ дан V Jo 14 April 2012 в 18:57
поделиться

CountDownLatch: Если мы хотим, чтобы все наши потоки выполняли

что-то + обратный отсчет

, чтобы другие ожидали ] (чтобы счетчик достиг нуля) нити могут продолжаться, мы можем использовать защелку обратного отсчета. Все предыдущие потоки, которые фактически выполняли обратный отсчет, могут в этом случае продолжить работу, но нет никакой гарантии, что строка , обработанная после latch.countdown (), будет после ожидания, когда другие потоки достигнут latch.countdown () , но он имеет гарантию, что другие ожидающие потоки будут запускаться дальше только после того, как latch.await () достигнет нуля.

CyclicBarrier: Если мы хотим, чтобы все наши потоки

делали что-то + ожидали в общей точке + делали что-то

( каждый вызов await будет уменьшать время ожидания продолжения потоков)

Функциональность CyclicBarrier может быть достигнута CountDownLatch только один раз, вызвав latch.countdown (), за которым следует latch.await () всеми потоками.

но снова вы не можете сбросить / использовать обратный отсчет.

Лучший пример, где я использовал CyclicBarrier, - это инициализация нескольких кэшей (нагретых несколькими потоками), а затем начало дальнейшей обработки, и я хотел снова инициализировать другие кэши в Sync.

1
ответ дан Rohit Sachan 14 April 2012 в 18:57
поделиться

Циклический барьер, как следует из названия, может использоваться в циклах. Например: я являюсь компанией, которая ищет N резюме из различных фидов порталов вакансий. У меня есть набор навыков, содержащий навыки, отсортированные в порядке приоритета. Для бывшей Java, C #, Python. Я хочу найти N резюме, совпадающее с набором навыков java, но если я не найду требуемого нет резюме, я снова ищу следующий набор навыков и т. д.

Я создаю работника, каждый из которых просматривает резюме в назначенных каналах. Оба работника начнут с поиска основного набора навыков в своих лентах вакансий.

После выполнения поиска работник проверит, были ли найдены N резюме. Если найден, работник сбросит шлагбаум и вернется. Иначе он будет ждать, пока другой работник завершит работу. Если все еще N резюме не были найдены, поиск будет возобновлен снова, на следующем навыке в наборе навыков. Таким образом, поиск можно вызывать рекурсивно / циклически, не создавая новый циклический барьер.

0
ответ дан user1849310 14 April 2012 в 18:57
поделиться

Вот мои наблюдения: -----> 1. После событий завершения: во время создания событие завершения не может быть передано в CountDownLatch, но оно может быть задано в CyclicBarrier.

  1. Количество: При создании CyclicBarrier число рабочих потоков не включает основной поток, если он также ожидает завершения других потоков. При создании CountDownLatch просто необходимо указать, сколько рабочих потоков будет ждать основной поток, чтобы завершить. В CountDownLatch существует концепция основного и рабочего потоков, и основной ожидающий поток не учитывается при создании защелки.

  2. Намерение await (): В CyclicBarrier :: await () все потоки, включая основной, равны и ждут друг друга. Следовательно, await () следует указывать во всех потоках (как рабочих, так и основных). CountDownLatch :: await () дается только в основном потоке и заставляет основной поток ждать, пока другие рабочие потоки не подсчитают до 0. Таким образом, внутренняя реализация обоих await () отличается.

  3. Стороны и ожидающие потоки: CountDownLatch не может дать число ожидающих потоков, но может дать стороны (cl.getCount ()), CyclicBarrier может не дать ожидающих потоков cb.getNumberWaiting () и стороны (cb.getParties (cb.getParties ( ))

  4. Рабочие обязанности: рабочий поток в обратном отсчете должен выполнять обратный отсчет (), а ожидание () выполняется одним основным потоком. В cyclicBarrier рабочий и основной потоки все делают только await () друг на друга.

  5. Повторное использование: CyclicBarrier можно использовать повторно. cb.await () работает для новых потоков, скажем, t1, t2 и main. И второй вызов cb.await () для новых потоков t3, t4 и main также работает. Main будет ожидать обоих вызовов, то есть система автоматически сбрасывает счет (или сбрасывает ()) после выхода из барьера. CountDownLatch не может быть повторно использован. - cl.await () работает для новых потоков, скажем, t1, t2 и main. Основной поток ожидает завершения t1, t2. Но для второго вызова cl.await () новые потоки t3, t4 и main не будут ждать.

Вот код для его поддержки ....

static class MyThread implements Runnable
{
    long waitTime;
    CyclicBarrier cyclicBarrier;
    CountDownLatch countdownlatch;
    MyThread(  long waitTime, CyclicBarrier cyclicBarrier, CountDownLatch countdownlatch){
        this.waitTime = waitTime;
        this.cyclicBarrier = cyclicBarrier;
        this.countdownlatch = countdownlatch;
    }
    @Override
    public void run() {

            try {

                Thread.sleep(waitTime);

                // Diff 4 -----> countdownlatch worker threads need to do countdown and await is done by one single main thread
                //, cyclicBarrier worker threads await on each other
                countdownlatch.countDown(); 
                cyclicBarrier.await();

                System.out.println("cyclicBarrier :: " + 
                        ", name :: " + Thread.currentThread().getName() 
                        + ", parties :: " + cyclicBarrier.getParties() 
                        + ", waiting :: "+ cyclicBarrier.getNumberWaiting()); 

                System.out.println("countdownlatch :: " + 
                            "name :: " + Thread.currentThread().getName()  +
                         ", parties :: "+countdownlatch.getCount() +
                         ", waiting :: " + "No method!!" ); 
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

    }

}

public static class MyCBFinishEvent implements Runnable{

    public void run() {

           System.out.println("All threads have reached common barrier point "
                        + ", CyclicBarrrierFinishEvent has been triggered");
           System.out.println("You can update shared variables if any");
    }

}

public static void main(String [] args) throws InterruptedException, BrokenBarrierException{
    //Diff 1 ----- > No finish event can be given in CountDownLatch
    //Diff 5 ------> CyclicBarrier no of worker threads includes main thread, 
    //CountDownLatch is just how many threads, the main waiting thread is not included in count.
    CyclicBarrier cb = new CyclicBarrier(3, new MyCBFinishEvent());
    CountDownLatch cl = new CountDownLatch(2);

    //Diff 2 ----> CountDownLatch cant give num of waiting threads, CyclicBarrier can getNumberWaiting threads
     System.out.println("Start CyclicBarrier - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("Start CountDownLatch - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

    Runnable t1 = new Thread(new MyThread( 10000, cb, cl));
    Runnable t2 = new Thread(new MyThread( 5000, cb, cl));
     Thread tt1 = new Thread(t1, "t1");
     Thread tt2 = new Thread(t2, "t2");
     tt1.start();
     tt2.start();

     //Diff 6 ---- > await meaning Main waits for t1 and t2 to complete, 
     //CyclicBarrier all are equal. each thread including main thread, if it wants to wait has to do await. 
     //CountDownLatch concept of waiting and workers. main thread await waits till other worker threads make count to 0.
     cb.await();
     cl.await();

     System.out.println("End CyclicBarrier call 1 - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("End CountDownLatch call 1 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     System.out.println("main start created t3, t4 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     Runnable t3 = new Thread(new MyThread( 6000, cb, cl));
        Runnable t4 = new Thread(new MyThread( 100, cb, cl));
         Thread tt3 = new Thread(t3, "t3");

         Thread tt4 = new Thread(t4, "t4");

         tt3.start();
         tt4.start();

        //Diff -3 -----> 
         //CyclicBarrier - can be reused, main thread waited for t3, t4 to complete.
         //CountDownLatch - for first cl.await(), main waited... second cl.await() call main did not wait!!! 
         cb.await();
         cl.await();


         System.out.println("End main - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
         System.out.println("end main parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

}
0
ответ дан BigQ 14 April 2012 в 18:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: