Java线程池的工作流程

图片参考链接:p1

 

图片参考链接:p2

 图片参考链接:p3

一个新的任务提交到线程池时:


    1.线程池判断核心线程池里的核心线程是否都在执行任务。 如果不是,让空闲的核心线程来执行任务。如果核心线程池里的线程都在执行任务,则进入下个流程。


    2.线程池判断阻塞队列是否已满。 如果阻塞队列没有满,则将新提交的任务存储在阻塞队列中。如果阻塞队列已满,则进入下个流程。



    3.线程池判断线程池里的线程数量是否小于最大线程数量(看线程池是否满了)。 如果小于,则创建一个新的工作线程(非核心线程,并给它设置超时时间,当我们处理完这些任务,无需手动销毁这个非核心线程,超时自动销毁)来执行任务。如果已满,则交给拒绝策略来处理这个任务。


之前学习线程池的工作流程的时候,

自己思考了一个问题,

新加入的任务和阻塞队列的任务抢占线程是公平的还是非公平的?

后来看线程池源码发现在核心线程还没满的时候,是非公平的,

核心线程满了是公平的,个人拙见,有误的话还望大佬指正。

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();//空指针异常
    /*
     * Proceed in 3 steps:
     *
     * 1. If fewer than corePoolSize threads are running, try to
     * start a new thread with the given command as its first
     * task.  The call to addWorker atomically checks runState and
     * workerCount, and so prevents false alarms that would add
     * threads when it shouldn't, by returning false.
     *
     * 2. If a task can be successfully queued, then we still need
     * to double-check whether we should have added a thread
     * (because existing ones died since last checking) or that
     * the pool shut down since entry into this method. So we
     * recheck state and if necessary roll back the enqueuing if
     * stopped, or start a new thread if there are none.
     *
     * 3. If we cannot queue task, then we try to add a new
     * thread.  If it fails, we know we are shut down or saturated
     * and so reject the task.
     */
/*

1. 如果正在运行的线程少于corePoolSize(核心线程数),尝试以给定命令作为第一个线程启动新线程任务。

   对addWorker的调用以原子方式检查运行状态和workerCount,从而防止可能增加在不应该的情况下,

   通过返回false执行线程。

2.如果任务可以成功排队,然后我们仍然需要再次检查是否应该添加线程

(因为自上次检查以来,已有的已死亡)或自进入此方法后池已关闭。

  所以我们要重新检查状态,如有必要,在停止排队时回滚排队,

  或者在没有排队时启动一个新线程。

3.如果我们无法将任务排队,那么我们将尝试添加一个新任务线程(非核心线程)。

  如果失败了,我们知道我们已经被关闭或饱和了,所以拒绝这个任务(执行拒绝策略)。

*/
    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();//再检查一边工作线程数量
        if (! isRunning(recheck) && remove(command))//判断是否有工作线程死亡以及阻塞队列中是否还有任务
            reject(command);//执行拒绝策略
        else if (workerCountOf(recheck) == 0)//工作线程为0的话(池已关闭)
            addWorker(null, false);
    }
    else if (!addWorker(command, false))//如果无法添加工作线程
        reject(command);//执行拒绝策略
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忧郁的叮当猫

Thanks♪(・ω・)ノ

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值