线程池解析

本文深入探讨了Java线程池的工作原理,包括执行Runnable任务的流程、线程池状态转换、阻塞工作队列类型及其特点。同时,文章详细阐述了任务拒绝策略,如AbortPolicy、DiscardPolicy等,并分析了Dubbo、Netty、PinPoint和ActiveMQ等框架中的自定义拒绝策略。此外,还介绍了Java提供的各种线程池类型及其应用场景,以及如何设置线程池的线程数。
摘要由CSDN通过智能技术生成

线程池解析

java线程对应内核线程,创建与销毁需要切换到内核态,是系统开销较大的操作,因此需要设法复用线程。线程池就是一个线程缓存,负责对线程统一分配,调优与监控,线程池的优势:

提高性能:重用线程减少线程创建消亡的开销
提高响应速度:任务到达时可以立即执行,不需要再去创建线程
方便管理线程:便于统一分配、调控和监控

执行Runnable任务流程

简单说处理任务的优先级为:核心线程、任务队列、最大线程,如果三者都满了,使用handler处理被拒绝的任务。

请添加图片描述

具体如何实现的呢?

/**
* 在将来某个时间执行该任务Runnable,可能是新建一个线程或者复用线程池已有的线程。
* 如果一个任务不能提交执行,要么是因为线程池shutdown了,要么是容量达到上限,此时执行拒绝策略
*/
public void execute(Runnable command) {
   
    if (command == null)
        throw new NullPointerException();
    // AtomicInteger原子变量,前3位表示状态,后29位表示线程数
    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {
   
        // 1. addWorker方法里面会原子检查当前running State和工作线程数目,防止并发时错误的多创建,
        // 也就是如果有别的线程添加任务达到corePoolSize,addWorker会返回false表示创建失败
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    
    if (isRunning(c) && workQueue.offer(command)) {
   
        // 2. 即使任务成功的入队,仍然需要再次检查是否应该增加线程,因为此时从last checking可能线程都死亡或者线程池shutdown
        int recheck = ctl.get();
        // 所以我们需要再次检查线程池状态,如果已经shutdown需要移除任务并拒绝该任务
        if (! isRunning(recheck) && remove(command))
            reject(command);
        // 如果线程都已死亡就新建一个
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
       
     // 如果入队失败,再尝试新建线程。如果失败说明线程池shutdown,或者饱和达到maximumPoolSize,应该执行拒绝策略
    }else if (!addWorker(command, false))
        reject(command);
}

另外很重要的方法addWorker(),注意调用此方法是用来新建线程

/**
* 检查是否可以根据当前池状态和给定界限(corePoolSize或maximumPoolSize)添加新的工作线程。
* 如果可能,将创建并启动一个worker,将firstTask作为其第一个任务运行。
* 如果池已stopped或shutdown中,或者threadfactory创建线程失败,则此方法返回 false。 
* 如果线程创建失败,或者threadfactory返回null,或者由于异常(通常是Thread.start()中的 OutOfMemoryError),我们会干净利落地回滚。
*
* @firstTask – 新线程应该首先运行的任务(如果没有,则为null)。当线程少于corePoolSize时(在这种情况下我们总是启动一个),
* 或者当队列已满(在这种情况下我们必须绕过队列)时,使用初始的第一个任务(在方法 execute() 中创建工作线程.
* 最初空闲线程通常通过 prestartCoreThread 创建或替换其他垂死的工人。
*/
private boolean addWorker(Runnable firstTask, boolean core) {
   
    retry:
    for (;;) {
   
        int c = ctl.get();
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;

        for (;;) {
   
            int wc = workerCountOf(c);
            if (wc >= CAPACITY ||
                // check线程数是否超过限制
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            if (compareAndIncrementWorkerCount(c))
                break retry;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }
    }

    boolean workerStarted = false;
    boolean workerAdded = false;
    Worker w = null;
    try {
   
        // 创建新的线程
        w = new Worker(firstTask);
        final Thread t = w.thread
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值