Циклический барьер в Java

У меня есть список, который должен быть заполнен тремя сторонами (скажем, потоками). Я использую циклический барьер для достижения этой функциональности. Все работает нормально, за исключением того, что я не могу использовать полученный список, не вызывая принудительный сон. Ниже приведен код:

public class Test{

List<Integer> item = new Vector<Integer>();

public void returnTheList(){
       CyclicBarrier cb = new CyclicBarrier(3, new Runnable() {

                @Override
                public void run() {

                    System.out.println("All parties are arrived at barrier, lets play -- : " + CyclicBarrierTest.getTheList().size());
                    //Here I am able to access my resulted list

                }
            });


            CyclicBarrierTest sw1 = new CyclicBarrierTest(cb, new ZetaCode(1500), s);
            CyclicBarrierTest sw2 = new CyclicBarrierTest(cb, new ZetaCode(1500),s);
            CyclicBarrierTest sw3 = new CyclicBarrierTest(cb, new ZetaCode(1500),s);
            Thread th1 = new Thread(sw1, "ZetaCode1");
            Thread th2 = new Thread(sw2, "ZetaCode2");
            Thread th3 = new Thread(sw3, "ZetaCode3");
            th1.start();
            th2.start();
            th3.start();

    }

public static void main(String args[]){
    System.out.println("asdfasd");
    Test test = new Test();
    //ActionClass ac = new ActionClass();
    test.returnTheList();
    System.out.println("Inside the main method...size of the final list : " +test.item.size() );
}

Ниже мой класс CyclicBrrierTest:

public class CyclicBarrierTest implements Runnable{

private CyclicBarrier barrier;
private Object obj;
 static volatile String s = "";
 volatile List<Integer> finalIntList = new Vector<Integer>();

public CyclicBarrierTest(CyclicBarrier barrier, Object obj, String s){
    this.barrier = barrier;
    this.obj = obj;
}

@Override
public void run(){
    try{
        System.out.println(Thread.currentThread().getName() + " is waiting on barrier and s is now  : " + finalIntList.size());
        ZetaCode simple = (ZetaCode)obj;

        finalIntList.addAll(simple.getTheItemList());
        barrier.await();

        System.out.println(Thread.currentThread().getName() + " has crossed the barrier");

    }catch(InterruptedException ex){
        System.out.println("Error.." + ex.getMessage());

    }catch(Exception e){
        System.out.println("Error.." + e.getMessage());
    }
}
    public  List<Integer> getTheList(){
    return finalIntList;
}

Итак, если я запускаю этот код без какой-либо задержки, оператор печати в моем основном методе дает мне длину моего списка как нулевую, однако после предоставления соответствующего сна он дает мне ожидаемый результат. Я хочу добиться того же, не давая никакой задержки .Любая помощь будет оценена. Заранее спасибо.


person viks1010    schedule 17.07.2014    source источник


Ответы (2)


Кажется, вы хотели бы использовать CountDownLatch< /a>, а не CyclicBarrier здесь. CyclicBarrier работает именно так, как предполагалось - ваш основной метод просто не ждет, пока его отключат все 3 потока. Когда вы даете ему оператор сна, другие 3 потока завершаются до того, как main снова просыпается.

CyclicBarrier полезен, когда вам нужно, чтобы N рабочих достигли одной и той же «контрольной точки», прежде чем продолжить, и сами рабочие — единственные, кому это нужно. Однако у вас есть пользователь N + 1, поток main, который хочет знать, когда они все закончат, а CyclicBarrier не поддерживает этот вариант использования.

Обратите внимание, конечно, что вы также можете использовать их оба.

person torquestomp    schedule 17.07.2014
comment
На самом деле CyclicBarrier соответствовал моим требованиям на начальном этапе. Позже я столкнулся с этой проблемой. Должен был предвидеть это. В любом случае спасибо за быстрый ответ :) - person viks1010; 17.07.2014
comment
В программном обеспечении замечательная и ужасная вещь — оно меняется :) - person torquestomp; 18.07.2014

В этом коде у нас есть 4 задачи. Task1, Task2, Task3, создающие значения int, и Task4 добавят все значения int. Task4 ожидает после вызова await() для Task1, Task2, Task3 для получения значений. Когда они производят значения, они вызывают метод await(), а Task 4 добавит свои значения и напечатает метод o/p и вызовет метод reset(), чтобы барьер будет сброшен. После сброса этот процесс продолжится снова

package practice;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicbarrierExample {

    public static void main(String[] args) {

        CyclicBarrier c = new CyclicBarrier(4);
        Task1 t1 = new Task1(c);
        Task2 t2 = new Task2(c);
        Task3 t3 = new Task3(c);
        Task4 t4 = new Task4(c);
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }
 }


class Task1 extends Thread {
    CyclicBarrier c;
    static int t1 ;

    public Task1(CyclicBarrier c) {
        this.c = c;
    }

    @Override
    public void run() {
        while (true) {
            t1 = t1 + 1;
            try {
                c.await();
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

class Task2 extends Thread {
    CyclicBarrier c;

    static int t2;

    public Task2(CyclicBarrier c) {
        this.c = c;
    }

    @Override
    public void run() {
        while (true) {
            t2 = t2 + 1;
            try {
                c.await();
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

}

class Task3 extends Thread {
    CyclicBarrier c;
    static int t3;

    public Task3(CyclicBarrier c) {
        this.c = c;
    }

    @Override
    public void run() {
        while (true) {
            t3 = t3 + 1;
            try {
                c.await();
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }

}

class Task4 extends Thread {
    CyclicBarrier c;
     static int t4;
    static int count=0;

    public Task4(CyclicBarrier c) {
        this.c = c;
    }

    @Override
    public void run() {
        while (count<10) {
            try {
                c.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            t4 = Task1.t1 + Task2.t2 + Task3.t3;
            System.out.println(t4);
            try {
                c.reset();
            } catch (Exception e) {
                System.out.println("yo");
            }
            count++;

        }
    }

}
person sumit    schedule 16.08.2019
comment
Не могли бы вы объяснить, что делает этот код и как он решает проблему? - person JJJ; 16.08.2019
comment
Привет JJJ, В этом коде у нас есть 4 задачи. Task1, Task2, Task3, создающие значения int, и Task4 добавят все значения int. Task4 ожидает после вызова await() для Task1, Task2, Task3 для получения значений. Когда они производят значения, они вызывают метод await(), а Task 4 добавит свои значения и напечатает метод o/p и вызовет метод reset(), чтобы барьер будет сброшен. После сброса этот процесс продолжится снова - person sumit; 16.08.2019