Art Java concurrent programming (15) CyclicBarrier

About CyclicBarrier

CyclicBarrier default constructor is CyclicBarrier (int parties), its parameter indicates the number of threads barrier to intercept each thread calls await method tells CyclicBarrier I have reached the barrier, then the current thread is blocked.

public class CyclicBarrierTest {
    static CyclicBarrier c = new CyclicBarrier(2);

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    c.await();
                } catch (Exception e) {
                }
                System.out.println(1);
            }
        }).start();
        try {
            c.await();
        } catch (Exception e) {
        }
        System.out.println(2);
    }
}

Should be the main thread and the child thread scheduling is determined by the CPU, two threads are likely to perform, it will produce two output

1
2
2
1

If the new CyclicBarrier (2) is modified to new CyclicBarrier (3), the main thread and a sub thread will wait forever, because there is no third thread await execution method, i.e. no third thread reaches the barrier, before it reaches the two barrier threads are not executed

CyclicBarrier also provides a more advanced constructor CyclicBarrier (int parties, Runnable barrierAction)
is used when the barrier arrival county, preferentially executed barrierAction, easy to handle more complex business scenario.

public class CyclicBarrierTest2 {
    static CyclicBarrier c = new CyclicBarrier(2, new A());  设置拦截线程的数量是2,所以必须等代码中的第一个线程和线程A都执行完之后,才会执行主线程。

    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    c.await();
                } catch (Exception e) {
                }
                System.out.println(1);
            }
        }).start();
        try {
            c.await();
        } catch (Exception e) {
        }
        System.out.println(2);
    }

    static class A implements Runnable {
        @Override
        public void run() {
            System.out.println(3);
        }
    }
}

CyclicBarrier scenarios

CyclicBarrier can be used for multi-threaded computing data, the combined results of the last scene.
For example, a user with an Excel save all bank water per Sheet save one account per bank water for nearly a year, and now need to count the user's daily water bank, the first bank to process each sheet in water use multithreading, after performing both to give each sheet of the average daily bank water, and finally, then barrierAction with the results of these threads, the entire Excel calculated average daily bank water

 银行流水处理服务类
public class BankWaterService implements Runnable {
    创建4个屏障,处理完之后执行当前类的run方法
    private CyclicBarrier c = new CyclicBarrier(4, this);
    假设只有4个sheet,所以只启动4个线程 ,使用线程池创建4个线程
    private Executor executor = Executors.newFixedThreadPool(4);
    保存每个sheet计算出的银流结果 
    private ConcurrentHashMap<String, Integer> sheetBankWaterCount = new ConcurrentHashMap<String, Integer>();

    private void count() {
        for (int i = 0; i < 4; i++) {
            executor.execute(new Runnable() {
                @Override
                public void run() {  计算当前sheet的银流数据,计算代码省略 
                    sheetBankWaterCount.put(Thread.currentThread().getName(), 1);  银流计算完成,插入一个屏障 
                    try {
                        c.await();
                    } catch (InterruptedException |
                            BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

    }

    @Override
    public void run() {
        int result = 0;  汇总每个sheet计算出的结果 
        for (Map.Entry<String, Integer> sheet : sheetBankWaterCount.entrySet()) {
            result += sheet.getValue();
        } 将结果输出 
        sheetBankWaterCount.put("result", result);
        System.out.println(result);
    }

    public static void main(String[] args) {
        BankWaterService bankWaterCount = new BankWaterService();
        bankWaterCount.count();
    }
}

CyclicBarrier and the difference CountDownLatch

CountDownLatch counter only be used once, and may be used CyclicBarrier counter reset () method to reset.
So CyclicBarrier can handle more complex business scenarios. For example, if the calculated error occurs, you can reset the counter and let the thread again from the beginning.
CyclicBarrier also provides other useful methods, such as getNumber Waiting ways to get the number of threads CyclicBarrier blocked. isBroken () method is used to find out if the blocked thread is interrupted.

public class CyclicBarrierTest3 {
    static CyclicBarrier c = new CyclicBarrier(2);

    public static void main(String[] args) throws InterruptedException,BrokenBarrierException

    {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    c.await();
                } catch (Exception e) {
                }
            }
        });
        thread.start();
        thread.interrupt();
        try {
            c.await();
        } catch (Exception e) {
            System.out.println(c.isBroken());
        }
    }
}

Output true

Published 24 original articles · won praise 1 · views 536

Guess you like

Origin blog.csdn.net/qq_45366515/article/details/105266707