CountDownLatch踩过的坑[通俗易懂]

CountDownLatch踩过的坑[通俗易懂]线上生产环境dubbo报线程池满了,经过一天排查锁定在开三个线程计算最后合并数据的步骤中。简单描述下该步骤线程开三个调用三个不同的方法使用countdownlatch计数器等待三个方法全部执行完成合并数据。但是由于其中一个方法调用第三方接口,接口返回异常导致转换数据报错。导致其中一个方法未正常完成。举例demo:publicstaticvoidmain(String[]a…

大家好,又见面了,我是你们的朋友全栈君。

线上生产环境dubbo报线程池满了,经过一天排查锁定在开三个线程计算最后合并数据的步骤中。简单描述下该步骤线程开三个 调用三个不同的方法 使用countdownlatch 计数器等待三个方法全部执行完成 合并数据。但是由于其中一个方法调用第三方接口,接口返回异常导致转换数据报错。导致其中一个方法未正常完成。

举例demo:

public static void main(String[] args) {
    ExecutorService executorService =Executors.newFixedThreadPool(3);
    CountDownLatch cdl = new CountDownLatch(3);
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            /*try {
                function1();
            } catch (Exception e) {
                //异常处理
                e.printStackTrace();
            }
            finally {
                cdl.countDown();
            }*/
            function1();
        }
    });

    executorService.execute(new Runnable() {
        @Override
        public void run() {
            function2();
            cdl.countDown();
        }
    });

    executorService.execute(new Runnable() {
        @Override
        public void run() {
            function3();
            cdl.countDown();
        }
    });


    try {
        cdl.await();
        //cdl.await(20,TimeUnit.SECONDS);
        System.out.println("三个执行线程结束");
    } catch (InterruptedException e) {
        e.printStackTrace();
        System.out.println("执行线程异常");
    }
    finally {
        executorService.shutdown();
        System.out.println("执行线程关闭");
    }


}

private static void function1(){
    int i = 10/0;
    System.out.println("方法一");
}

private static void function2(){
    System.out.println("方法二");
}

private static void function3(){
    System.out.println("方法三");
}

CountDownLatch踩过的坑[通俗易懂]

方法一抛出异常,但是没有做异常处理导致不会执行线程关闭步骤,是不是和想象中不一样,一开始我也是懵,看了一下CountDownLatch原理就很好理解了,

“CountDownLatch是通过一个计数器来实现的,计数器的初始化值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已完成任务,然后在闭锁上等待的线程就可以恢复执行任务。”【1】

举一个现实中例子就是:CountDownLatch 就像跑步比赛中的裁判,三个方法就是就是三位运动员,运动员2,3都已经到达终点,但是运动员1摔倒了,动不了。裁判员只看到两位运动员到达终点不能宣布比赛结束,所以一直等。。。 

就像这样的场景导致线上service执行线程阻塞,接口调用次数累计导致dubbo线程满了(跟dubbo线程模型有关,有时间具体谈谈这一点)

知道原因了,就要考虑怎么修改

比赛不能无限期等,所以比赛必须在有限时间内结束,所以使用

public boolean await(long timeout, TimeUnit unit)
    throws InterruptedException {
    return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}

线程内部也许要增加异常处理

executorService.execute(new Runnable() {
    @Override
    public void run() {
        try {
            function1();
        } catch (Exception e) {
            //异常处理
            e.printStackTrace();
        }
        finally {
            cdl.countDown();
        }
       // function1();
    }
});

修改后demo

public static void main(String[] args) {
    ExecutorService executorService =Executors.newFixedThreadPool(3);
    CountDownLatch cdl = new CountDownLatch(3);
    executorService.execute(new Runnable() {
        @Override
        public void run() {
            try {
                function1();
            } catch (Exception e) {
                //异常处理
                e.printStackTrace();
            }
            finally {
                cdl.countDown();
            }
           // function1();
        }
    });

    executorService.execute(new Runnable() {
        @Override
        public void run() {
            function2();
            cdl.countDown();
        }
    });

    executorService.execute(new Runnable() {
        @Override
        public void run() {
            function3();
            cdl.countDown();
        }
    });


    try {
       // cdl.await();
        cdl.await(20,TimeUnit.SECONDS);
        System.out.println("三个执行线程结束");
    } catch (InterruptedException e) {
        e.printStackTrace();
        System.out.println("执行线程异常");
    }
    finally {
        executorService.shutdown();
        System.out.println("执行线程关闭");
    }


}

private static void function1(){
    int i = 10/0;
    System.out.println("方法一");
}

private static void function2(){
    System.out.println("方法二");
}

private static void function3(){
    System.out.println("方法三");
}

执行结果

CountDownLatch踩过的坑[通俗易懂]

大家结合自己的现实使用修改,爬过了使用坑,记录下分享下 ,希望能对别人有用

【1】参考https://www.jianshu.com/p/4b6fbdf5a08f

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/158775.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • c语言中图书管理系统_c语言图书管理系统排序

    c语言中图书管理系统_c语言图书管理系统排序课件C语言图书管理系统代码#include#include#includestructbook{intnum;charbname[50];charwname[20];charpress[50];charsort[50];inttime;floatprice;structbook*next;};structbook*creatbook();…

  • mac远程连接mysql「建议收藏」

    mac远程连接mysql「建议收藏」sudosshroot@IPmysql-uroot-p-hIP

    2022年10月13日
  • SD卡、TF卡、MMC卡以及eMMC芯片的介绍「建议收藏」

    SD卡、TF卡、MMC卡以及eMMC芯片的介绍「建议收藏」一、SD卡   1、简介       SD卡为SecureDigitalMemoryCard,即安全数码卡,是一种基于半导体快闪记忆器的新一代记忆设备。它在MMC的基础上发展而来,增加了两个主要特色:SD卡强调数据的安全,可以设定所储存的使用权限,防止数据被他人复制;另外一个特色就是传输速度比2.11版的MMC卡快。   2、外观及引脚定义   3、特性

  • Python3网络爬虫快速入门实战解析

    Python3网络爬虫快速入门实战解析请在电脑的陪同下,阅读本文。本文以实战为主,阅读过程如稍有不适,还望多加练习。本文的实战内容有:网络小说下载(静态网站)、优美壁纸下载(动态网站)、爱奇艺VIP视频下载PS:本文为Gitchat线上分享文章,该文章发布时间为2017年09月19日。

  • 阿里云申请免费ssl证书及安装_申请免费ssl证书

    阿里云申请免费ssl证书及安装_申请免费ssl证书本文参考以下文章并整理:阿里云SSL证书免费申请方法(图文教程)藏羚骸的博客~阿里云SSL证书部署(DigiCert免费版SSL)2022阿里云免费SSL证书品牌为DigiCertDV单域名证书,每个阿里云账号可以申请20个免费SSL证书资源包,SSL证书大全图文详解阿里云SSL证书免费申请和部署教程,包括SSL证书申请域名DNS验证等操作。阿里云DigiCert免费版SSL有效期一年,过期后需要重新部署SSL。所以,不管是第一次部署SSL还是刚接手公司项目SSL就到期的小伙伴都可

  • 用计算机套路别人,套路计算器隐藏版[通俗易懂]

    用计算机套路别人,套路计算器隐藏版[通俗易懂]套路计算器隐藏版是款非常适合撩妹的神器,各种整蛊玩法,套路你的女朋友,操作简单,不需要root免费使用,轻松的哄女朋友开心。套路计算器隐藏版特色1.在这里都可以跟你的好友们设定任何的计算套路。2.在使用的时候看起来就跟普通的计算器应用差不多。3.他的套路秘诀就在输入计算结果之后,会显示提前设定的文字。4.各种的文章内容都可以设定到计算里面。套路计算器隐藏版怎么用进入的先设置好内容,进入后打开的都是…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号