zoukankan      html  css  js  c++  java
  • 线程、调度线程池、异常

    看dubbo源码的时候,发现下面一段代码。前段时间,因为也是类似的线程池,遇到一个坑,刚好这次又看到,所以准备好好研究下下面的粗体字设计的三个知识点:
    线程、调度线程池、异常。
    public class DubboMonitor implements Monitor {
    private static final Logger logger = LoggerFactory.getLogger(DubboMonitor.class);
    // 定时任务执行器
    private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3, new NamedThreadFactory("DubboMonitorSendTimer", true));

    public DubboMonitor(Invoker<MonitorService> monitorInvoker, MonitorService monitorService) {
    // 启动统计信息收集定时器
    sendFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
    public void run() {
    // 收集统计信息
    try {
    send();
    } catch (Throwable t) { // 防御性容错
    logger.error("Unexpected error occur at send statistic, cause: " + t.getMessage(), t);
    }
    }
    }, monitorInterval, monitorInterval, TimeUnit.MILLISECONDS);
    }
    ...
    线程与异常:1、异常是线程隔离的,简单讲就是如果某个线程中抛出了异常,其他线程是无法感知到的。我们对照dubbo的上面一段代码看下。
    定时收集器的调度线程池(scheduledExecutorService)在启动各个子线程的时候,用了catch Throwable ,其实我们正常情况下,绝大部分时间都是直接catch到exception
    这里为啥要到
    Throwable呢? 其实这个还是很讲究的,
    我们看下
    scheduleWithFixedDelay的签名:
    If any execution of the task encounters an exception, subsequent executions are suppressed.
    如果任何一次执行遇到异常,后面的执行将会被压制即无法继续执行。
    我之前使用的时候,只是捕获到exception,偶尔线上会出现任务不执行的情况,当时也不知道怎么回事,每次出现问题,并没有任何异常日志。因为
    你在主线程无法捕获到线程池的子线程
    里面的异常,所以当某个任务子线程抛出throwable时,主线程发现不了,这个异常信息也无法记录,所以很难定位,当时
    只能通过重启项目解决。后来重构的时候,研究了线程池和异常的关系,
    才找到具体的原因。
    所以dubbo里面的直接捕获到Throwable,还是很讲究的。

    总结,如果用调度线程池来做业务,一定要catch到
    Throwable,以免出现小概率的问题,而无法定位。








  • 相关阅读:
    kubernetes概述与入门
    kubernetes入门到放弃-docker基础篇
    Git远程仓库☞GitLab的使用
    Git远程仓库☞GitHub的使用
    Git版本控制系统
    持续集成-DevOps概念篇
    持续集成扫盲篇
    Centos7系统介绍
    LNMP架构说明
    dynamic_cast c++
  • 原文地址:https://www.cnblogs.com/yipihema/p/6972826.html
Copyright © 2011-2022 走看看