java线程池(2)-线程池添加任务的过程(原理)

    上一期简单的聊了一下线程池的创建。这一期我们就,稍微熟悉一下线程池执行任务的过程吧!

    线程池的工作原理是怎么样的呢?
    首先,我用图来说明吧!
这里写图片描述
    这里可以看到有一个任务队列,然后还有一个工作的线程池。今天主要将的就是向任务队列中添加任务的过程!
    对于线程池我们上一期是做了一个稍微的解释的。我们构建线程池的时候,无论我们传入队列或者是不传入最后都会有一个队列的。那么这个队列是用来干什么的呢?当我们提交的任务不能被及时执行的时候,可以入队列,等待被执行的。现在对于线程池的提交任务流程做一个简单的图解。
这里我们主要以cachedThreadPool为例。

线程池传入要执行的任务流程图
图中所有创建的线程都会被放到线程池的hashset中记录下来!
这个流程图大概分为以下几个部分:

  1. 提交任务首先判断是否是null,如果是null就抛出空指针异常,如果不是执行2。
  2. 判断线程池中工作的线程数是否小于核心线程池的大小。如果小于执行 3,如果大于执行4
  3. 创建一个线程来执行提交的任务,如果失败重新获取线程池状态,然后执行4,成功就返回
  4. 判断线程池的状态是否在运行和尝试向把任务加入等待队列,如果线程池已经关闭或者放入等待队列失败,执行6。如果放入队列成功执行5
  5. 因为成功的入队了,我们需要重新判断线程池的状态,因为在放入队列的过程中线程池的状态可能会发生变化。如果发现线程池的状态不是在运行就将刚才添加的任务从队列中移除,然后执行拒绝策略。如果是在运行状态执行7
  6. 尝试创建一个线程来执行任务,如果创建线程失败就执行拒绝策略
  7. 判断当前的工作线程数是不是0如果不是就返回,如果是就创建一个线程!
    public void execute(Runnable command) {
        //首先判断传入的线程是不是null,没什么好说的
        if (command == null)
            throw new NullPointerException();
        //这里的ctl是什么呢? private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));这是一个原子操作类,
        //线程池里面对这个原子操作类做出了,比较清晰的解释的。我大概在这里说一下吧。这个整数有一共32位,其中最高三位用来,存储线程池的状态。低29位用来存储线程池活跃的线程数目。
        //线程池的状态一共有以下几种情况
        //正在运行,能够接受新任务,以及对应添加的任务进行处理
        //private static final int RUNNING    = -1 << COUNT_BITS;
        //关闭,不接受新的任务但是可以处理已经添加的任务
        //private static final int SHUTDOWN   =  0 << COUNT_BITS;
        //停止,不接受新任务,但是也不会处理已经添加的任务。
        //private static final int STOP       =  1 << COUNT_BITS;
        //整理,所有的任务都已经处理结束线程池的状态。这个时候线程池会执行一个函数terminated()现在模拟人的处理都是空的
        //private static final int TIDYING    =  2 << COUNT_BITS;
        //线程池彻底的终止。整理状态调用terminated函数以后就会变成这个状态了
        //private static final int TERMINATED =  3 << COUNT_BITS;


        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();
            //如果成功入队的话,我们需要重新的判断一下状态,因为从上一次check、到现在可能会有线程死亡,或者线程池关闭了。如果线程池关闭了我们就拒绝这个任务,如果有线程死亡我们就创建新的线程
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //创建线程失败了,就拒绝任务就好了!
        else if (!addWorker(command, false))
            reject(command);
    }

    大家可能发现了,执行任务的时候有一个submit还有一个execute这两个方法的区别就是:submit会返回一个异步的结果。但是execute方法没有返回值。这个很清楚吧!
    个人认为单就提交任务的 流程算是比较清楚了!本期没有代码,因为分析的都是源码!想看代码的小伙伴们可以直接看jdk1.7的源代码!欢迎交流!
    现在很多电影都有彩蛋,这个线程池系列也来了个彩蛋吧!下一期将会说一下创建新线程添加到hashset和线程池的关闭过程!敬请期待!!!

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java线程池的工作原理是这样的:首先,线程池在创建时会向系统申请一个用于执行线程队列和管理线程池线程资源。然后,在调用execute()方法添加一个任务时,线程池会按照以下流程执行任务。 1. 当线程池接收到一个新任务时,会判断线程池中是否有空闲的线程可用。如果有,就将任务分配给其中一个空闲线程;如果没有,就将任务添加线程队列中等待执行。 2. 线程池会从线程队列中选择一个任务,然后将其分配给一个空闲的线程执行。 3. 执行任务线程会从任务队列中取出任务,然后执行任务的代码逻辑。 4. 任务执行完毕后,线程并不会被销毁,而是会再次回到线程池中成为空闲状态,等待下一个任务的到来。 5. 如果线程池中的线程数量超过了设定的最大线程数,多余的线程会被暂时停用。当任务队列中有新任务到来时,线程池会再次激活这些暂时停用的线程来执行任务Java中的线程池是通过Executor框架来实现的,其中使用了Executor、Executors、ExecutorService、ThreadPoolExecutor、Callable、Future、FutureTask等核心类。这些类提供了方便的方法来管理线程池的创建、执行和结束等操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Java 线程池的工作原理](https://blog.csdn.net/weixin_45970271/article/details/125408580)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值