Concurrent常用工具类的使用(CyclicBarrier/CountDownLatch/Callable)

Concurrent.Util常用类

CyclicBarrier

假设有一个场景:每个线程代表一个运动员,当运动员都准备好才一起出发,只要有一个没准备好就大家都等待。

public class UseCyclicBarrier {

    static class Runner implements Runnable{

        private CyclicBarrier barrier;
        private String name;

        public Runner(CyclicBarrier barrier,String name){
            this.barrier=barrier;
            this.name=name;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(1000*(new Random().nextInt(5)));
                System.out.println(name+" 准备OK.");
                barrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println(name+" Go!!!");
        }

    }

    public static void main(String[] args) {
        //3表示要等待三个线程
        CyclicBarrier barrier = new CyclicBarrier(3);
        ExecutorService executor = Executors.newFixedThreadPool(3);
        executor.submit(new Thread(new Runner(barrier,"zhangsan")));
        executor.submit(new Thread(new Runner(barrier,"lisi")));
        executor.submit(new Thread(new Runner(barrier,"wangwu")));
        executor.shutdown();
    }
}

CountDownLatch

它经常用于监听某些初始化操作,等初始化执行完毕后,通知主线程继续工作。

public class UseCountDownLatch {

    public static void main(String[] args) {

        final CountDownLatch countDownLatch = new CountDownLatch(2);
        Thread t1 = new Thread(new Runnable(){
            @Override
            public void run() {
                try {
                    System.out.println("进入线程1"+"等待其他线程处理完成...");
                    countDownLatch.await();
                    System.out.println("t1线程继续执行...");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t1");

        Thread t2 = new Thread(new Runnable(){
            @Override
            public void run() {
                try {
                    System.out.println("t2线程初始化操作...");
                    Thread.sleep(3000);
                    System.out.println("t2线程初始化完毕,通知t1线程继续...");
                    countDownLatch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        },"t2");

        Thread t3 = new Thread(new Runnable(){
            @Override
            public void run() {
                try {
                    System.out.println("t3线程进行初始化操作...");
                    Thread.sleep(4000);
                    System.out.println("t3线程初始化完毕,通知t1线程继续...");
                    countDownLatch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"t3");
        t1.start();
        t2.start();
        t3.start();
    }

}

CountDownLatch与CyclicBarrier的区别

CountDownLatch是一个线程在等待其他线程的通知,然后一个线程执行。
CyclicBarrier是几个线程都参与阻塞。当阻塞条件达到,所有的线程都同时执行。

Callable和Future的使用

类似于之前Future模式的使用,JDK给予了一个实现的封装。

public class UseFuture implements Callable<String>{
    private String para;

    public UseFuture(String para){
        this.para=para;
    }

    /**
     * 真实的业务逻辑,其执行可能很慢
     */
    @Override
    public String call() throws Exception {
        //模拟执行耗时
        Thread.sleep(3000);
        String result = this.para+"处理完成";
        return result;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        String queryStr = "query";
        //构建FutureTask,并且传入需要真正进行业务处理的类,该类一定是实现了Callable接口的类
        FutureTask<String> future = new FutureTask<String>(new UseFuture(queryStr));
        FutureTask<String> future2 = new FutureTask<String>(new UseFuture(queryStr));
        //创建一个固定线程的线程池且线程数为1
        ExecutorService executor = Executors.newFixedThreadPool(2);
        //这里提交任务future,则开启线程执行RealData的call()方法执行
        //submit和executor的区别:第一点 submit可以传入实现callable接口的实力对象 第二点 submit方法有返回值
        Future f1 = executor.submit(future);
        Future f2 = executor.submit(future2);
        System.out.println("请求完毕");
        //当返回值为null 表示执行结束
        /*System.out.println(f.get());
        while(true){
            if(f.get()==null){
                System.out.println("当前线程执行完毕...");
                break;
            }
        }*/

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //调用获取数据方法,如果call()方法没有执行完成,则依旧会等待,get()方法异步获取执行结果
        System.out.println("数据:"+future.get());
        System.out.println("数据:"+future2.get());
        executor.shutdown();

    }
}

Semaphore信号量非常适合高并发访问,新系统上线之前,要对新系统的访问量进行评估,当然这个值不能太大也不能太小。太大的话浪费资源,太小的话某个高峰值的访问量上来直接压垮系统。
相关概念:
PV(page view)网站的总访问量,页面浏览量或点击量,用户没刷新一次就会被记录一次。
UV(unique visitor)访问网站的一台电脑客户端为一个访客。一般来说0点-24点只能相同ip的客户端只记录一次。
QPS(query per seconds)即每秒查询量
RT(response time)请求的响应时间。
峰值qps=(总PV*0.8)/(60*60*24*0.2)

/**
 * 使用semaphore进行限流的控制
 * @author Carl_Hugo
 */
public class UseSemaphore {

    public static void main(String[] args) {
        //没有容量限制的线程池
        ExecutorService exec = Executors.newCachedThreadPool();
        //只能5个线程同时访问
        final Semaphore semp = new Semaphore(5);
        //模拟20个客户端访问
        for(int index=0;index<20;index++){
            final int NO = index;
            Runnable run = new Runnable(){
                @Override
                public void run() {
                    try {
                        //获取许可
                        semp.acquire();
                        System.out.println("Accessing:"+NO);
                        //模拟实际业务逻辑
                        Thread.sleep((long)(Math.random()*10000));
                        //访问完后释放
                        semp.release();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            };
            exec.execute(run);
        }

        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        exec.shutdown();
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值