【个人笔记】线程池为何要构建空任务的非核心线程?

看源码https://segmentfault.com/a/1190000044699924
当核心线程满了时,先放阻塞队列,阻塞队列满了才去申请非核心线程!

public void execute(Runnable command){
    if(command = nul1)
        throw new NullPointerException();
    /*...*/
    int c= ctl.get();
    if(workerCountOf(c) < corePoolSize){ 
        // 当前活跃线程数小于核心线程数,则创建核心线程
        if(addWorker(command, true))  
           return; // 创建成功
        c=ctl.get();
    }
    // 创建失败,核心线程满了,尝试放入阻塞队列
    if(isRunning(c) && workQueue.offer(command)){ 
        int recheck=ctl.get();
        // 再次确认:判断当前线程池状态是否为running(运行中)
        if(!isRunning(recheck) && remove(command))  // 如果不是running状态,需要将任务从核心队列中清除
            reject(command);   // 并执行拒绝策略
        else if(workerCountOf(recheck)==0) 
            // 构建空任务的非核心线程(core=false)
            addWorker(null, false); 
    // 放入阻塞队列失败,阻塞队列满了,尝试创建非核心线程执行任务
    }else if(!addWorker(command,false))  
        // 非核心线程创建失败,可能是因为队列已满或线程池配置不允许放入更多任务,执行拒绝策略。
        reject(command);  
}

在一个新任务进来时,如果核心线程数设置为0或者设置核心线程的存活时间导致超时被销毁,线程池内无核心线程可用(因为阻塞队列没满,所以也没有非核心线程)但是新任务被放到了阻塞队列,这种情况会导致任务一直在队列中放着(任务会饥饿),所以需要添加非任务的空核心线程避免任务饥饿。
为什么不直接addWorker(command, false)而是addWorker(null, false)?
因为线程池的设计理念之一是任务一旦成功放入阻塞队列,应该依赖线程池中的线程从队列中提取任务并执行,而不是在入队后直接将任务交给新创建的线程。
所以此时任务已经在阻塞队列里面了,不要直接把任务交给线程,而是让一个空闲线程从队列里面获取任务来执行。
(通过调用 addWorker(null, false),新创建的线程会自动从队列中获取任务,这符合线程池的工作流程,保持了线程池操作的简单和一致性。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值