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)
blank

相关推荐

发表回复

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

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