zoukankan      html  css  js  c++  java
  • Java高并发编程基础三大利器

    1. 什么是CountDownLatch

    CountDownLatch是一个线程倒计时锁。

    CountDownLatch是通过一个计数器来实现的,计数器的初始值是线程的数量。
    每当一个线程执行完毕后,计数器的值就减1,
    当计数器的值为0时,表示所有线程都执行完毕,
    然后在闭锁上(调用await方法的线程)等待的线程就可以恢复工作了。

    2. 应用场景


    把一个大任务拆分N个部分,让多个工作线程(Worker)执行。
    每个工作线程(Worker)执行完自己的部分计数器就减1。
    当所有子部分都完成后,主线程才继续向下执行。

    例子代码:

    public class TestCountDownLatch1 {
         public static void main(String[] args) throws InterruptedException {
              int count = 3;
              CountDownLatch countDownLatch = new CountDownLatch(count);
              for (int i = 0; i < count; i++) {
                   final int index = i;
                   new Thread(() -> {
                        try {
                             Thread.sleep(1000 + ThreadLocalRandom.current().nextInt(1000));
                             System.out.println("finish" + index + Thread.currentThread().getName());
                        } catch (InterruptedException e) {
                             e.printStackTrace();
                        }finally{
                            countDownLatch.countDown();
                        }
                   }).start();
              }
    
             // 主线程在阻塞,当计数器==0,就唤醒主线程往下执行
              countDownLatch.await();
              
              System.out.println("主线程:在所有任务运行完成后,进行结果汇总");
         }
    }

    更实际的例子:

    我们打开一个电商的个人中心页面。
    在该页面, 我们需要调用:
    1. 用户信息接口
    2. 用户订单接口
    3. 用户会员信息等接口

    然后合并后一起给到前端。
    假设每个接口最长耗时为1s,如果我们同步调用的话最大耗时时间是3s,
    如果我们采用异步调用然后合并结果,所以最大的耗时时间是3s。
    每个接口调用返回数据后调用countDown方法,让计数器进行减1,
    当把计数器减为0时的这个线程会去唤醒主线程,让它继续往下走。

    3. CountDownLatch 实现原理

    CountDownLatch是通过AQS的state字段来实现的一个计数器。

    计数器的初始值(state的值)为new CountDownLatch设置的数量,
    每次调用countDown的时候,state的值会进行减1,
    最后某个线程将state值减为0时,会把调用了await()进行阻塞等待的线程进行唤醒。
    CountDownLatch重写了tryReleaseShared这个方法,
    只有当state这个字段被设置为0时,也就是tryReleaseShared返回true的情况就会执行doReleaseShared方法,
    把调用了await的线程进行唤醒。


    部分源码:
    public final boolean releaseShared(int arg) {
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }
    
    protected boolean tryReleaseShared(int releases) {
        // Decrement count; signal when transition to zero
        for (;;) {
            int c = getState();
            if (c == 0)
                return false;
            int nextc = c-1;
            if (compareAndSetState(c, nextc))
                return nextc == 0;
        }
    }


     
    技术改变世界
  • 相关阅读:
    Qt之JSON生成与解析
    Qt的QLineEdit显示密码
    Ubuntu14.04 64位运行32位程序
    Xcode 7在支持ipad的设备中需要支持分屏!
    「模板」平衡树
    [NOI2016]区间 题解(决策单调性+线段树优化)
    [NOIP模拟测试12]题解
    [笔记乱写]0/1分数规划
    [NOIP模拟测试11] 题解
    [SCOI2014]方伯伯的玉米田 题解(树状数组优化dp)
  • 原文地址:https://www.cnblogs.com/davidgu/p/14682973.html
Copyright © 2011-2022 走看看