tomcat和dubbo对于JDK线程池的修改

本文探讨了Tomcat和Dubbo针对JDK线程池的优化,着重分析了Tomcat如何扩展ThreadPoolExecutor以适应大量IO密集型任务,包括自定义ThreadPoolExecutor和TaskQueue,以及增加重试策略。Dubbo同样采用了类似的方法,通过自定义线程池和任务队列来改进线程池的执行机制。
摘要由CSDN通过智能技术生成

预备知识

  • 计算任务的分类

    • CPU密集型:需要线程长时间进行的复杂的运算,这种类型的任务需要少创建线程,过多的线程将会频繁引起上文切换,降低任务处理处理速度。
    • IO密集型:由于线程并不是一直在运行,可能大部分时间在等待 IO 读取/写入数据,增加线程数量可以提高并发度,尽可能多处理任务。
  • JDK线程池,java.util.concurrent.ThreadPoolExecutor 传说中的7个参数,作用,线程池运行机制,参见下图复习

在这里插入图片描述

概述

结合ThreadPoolExecutor的运行过程,可以知道ThreadPoolExecutor主要倾向于CPU密集型任务,但对于对于 io 密集型任务,如数据库查询,rpc 请求调用等,就不是很友好。

由于 Tomcat/Jetty 需要处理大量客户端请求任务,如果采用原生线程池,一旦接受请求数量大于线程池核心线程数,这些请求就会被放入到队列中,等待核心线程处理。这样做显然降低这些请求总体处理速度,所以两者都没采用 JDK 原生线程池。

Jetty选择自己实现线程池组件,可以定制化开发,但难度较大,而Tomcat选择扩展ThreadPoolExecutor,相对比较简单。

Tomcat线程池源码分析

Tomcat源码中,为扩展线程池,主要修改了:

  • 自定义ThreadPoolExecutor,直接继承JDK的ThreadPoolExecutor,重写部分逻辑
  • 实现TaskQueue,直接继承LinkedBlockingQueue ,重写 offer 方法。

ThreadPoolExecutor

线程池核心方法execute(),Tomcat简单做了修改,还是将工作任务交给父类,也就是Java原生线程池处理,但增加了一个重试策略。如果原生线程池执行拒绝策略的情况,抛出 RejectedExecutionException 异常。这里将会捕获,然后重新再次尝试将任务加入到 TaskQueue ,尽最大可能执行任务。

public void execute(Runnable command, long timeout, TimeUnit unit) {
   
        this.submittedCount.incrementAndGet();

        try {
   
            super.execute(command);
        } catch (RejectedExecutionException var9) {
   
            if (!(super.getQueue() instanceof TaskQueue)) {
   
                this.submittedCount.decrementAndGet();
                throw var9;
            }

            TaskQueue queue = (TaskQueue)super.getQueue();

            try {
   
                //拒绝后,再尝试入队,还不行则抛出异常
                if (!queue.force(command, timeout, unit)) {
   
                    this.submittedCount.decrementAndGet();
                    throw new RejectedExecutionException(sm.getString("threadPoolExecutor.queueFull"));
                }
            } catch (InterruptedException var8) {
   
                this.submittedCount.decrementAndGet();
                throw new RejectedExecutionException(var8);
            }
        }
    }

需要注意 submittedCount 变量。这是 Tomcat 线程池内部一个重要的参数,它是一个 AtomicInteger 变量,将会实时统计已经提交到线程池中,但还没有执行结束的任务。也就是说 submittedCount 等于线程池队列中的任务数加上线程池工作线程正在执行的任务。

TaskQueue


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值