JAVA中的并发工具类(二)---同步屏障类CyclicBarrier

本文涉及到的源码可以在我的github找到。

CyclicBarrier的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障点时均被阻塞,只要规定数目的线程都到达该处,然后同时放行。

应用场景:多线程计算数据,最后合并结果的场景。例如,用一个Excel保存用户所有银行流水,每个sheet保存一个账户近一年的每笔流水,现在需要统计用户的日均银行流水,先用多线程处理每个sheet,都执行完之后,得到每个sheet的日均流水,最后,再用这些计算结果进行汇总计算。

首先是一个比较容易理解的Demo:

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

public class CyclicBarrierDemo
{

    public static void main(String[] args)
    {
        ExecutorService pool = Executors.newFixedThreadPool(3);

        CyclicBarrier barrier = new CyclicBarrier(3);

        for (int i = 0; i < 3; i++)
        {
            Runnable runable = new Runnable()
            {

                @Override
                public void run()
                {
                    try
                    {
                        // TODO Auto-generated method stub
                        Thread.sleep((long) (Math.random() * 10000));
                        System.out.println(Thread.currentThread().getName() + "已经到达地点AAAA,当前到达数:"
                                + (barrier.getNumberWaiting() + 1)
                                + (barrier.getNumberWaiting() == 2 ? "  全部到达,继续走。" : "等待伙伴..."));
                        barrier.await();

                        Thread.sleep((long) (Math.random() * 10000));
                        System.out.println(Thread.currentThread().getName() + "已经到达地点BBBB,当前到达数:"
                                + (barrier.getNumberWaiting() + 1)
                                + (barrier.getNumberWaiting() == 2 ? "  全部到达,继续走。" : "等待伙伴..."));
                        barrier.await();
                        Thread.sleep((long) (Math.random() * 10000));
                        System.out.println(Thread.currentThread().getName() + "已经到达地点CCCC,当前到达数:"
                                + (barrier.getNumberWaiting() + 1)
                                + (barrier.getNumberWaiting() == 2 ? "  全部到达,继续走。" : "等待伙伴..."));
                        barrier.await();
                    } catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            };

            pool.execute(runable);

        }
        pool.shutdown();
    }
}

运行结果如下:

pool-1-thread-3已经到达地点AAAA,当前到达数:1等待伙伴...
pool-1-thread-1已经到达地点AAAA,当前到达数:2等待伙伴...
pool-1-thread-2已经到达地点AAAA,当前到达数:3  全部到达,继续走。
pool-1-thread-3已经到达地点BBBB,当前到达数:1等待伙伴...
pool-1-thread-2已经到达地点BBBB,当前到达数:2等待伙伴...
pool-1-thread-1已经到达地点BBBB,当前到达数:3  全部到达,继续走。
pool-1-thread-3已经到达地点CCCC,当前到达数:1等待伙伴...
pool-1-thread-1已经到达地点CCCC,当前到达数:2等待伙伴...
pool-1-thread-2已经到达地点CCCC,当前到达数:3  全部到达,继续走。

下面是一个应用场景:

import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BankWaterService implements Runnable
{

    // 屏障
    private CyclicBarrier barrier = new CyclicBarrier(4);
    // 线程池
    private ExecutorService pool = Executors.newFixedThreadPool(4);
    // 保存结果的map
    private ConcurrentHashMap<String, Integer> order = new ConcurrentHashMap<>();

    private void count()
    {
        for (int i = 0; i < 4; i++)
        {
            Runnable action = new Runnable()
            {

                @Override
                public void run()
                {
                    // TODO Auto-generated method stub
                    order.put(Thread.currentThread().getName(), 4);// 模拟计算出的结果放入map
                    try
                    {
                        barrier.await();
                    } catch (Exception e)
                    {
                        // TODO: handle exception
                    }
                }
            };

            pool.execute(action);

        }

        pool.shutdown();
    }

    @Override
    public void run()
    {
        int result = 0;
        for (Entry<String, Integer> entry : order.entrySet())
        {
            result += entry.getValue();// 新开启线程对结果进行统计
        }

        System.out.println("总结果:"+result);
    }

    public static void main(String[] args)
    {
        BankWaterService service = new BankWaterService();
        service.count();
        Thread thread = new Thread(service);

        try
        {
            Thread.sleep(10000);//使得线程充分运行。
        } catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        thread.start();
    }

}

结果:

总结果:16
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值