当前位置:   article > 正文

Java并发编程系列33:线程池ThreadPoolExecutor工作流程_java线程池工作流程

java线程池工作流程

线程池ThreadPoolExecutor工作流程

Java线程池主要是用于合理创建线程,减少线程创建销毁频率(线程复用、线程资源管理),最大限度利用CPU性能。

线程池(这里说的是ThreadPoolExecutor)工作流程分3步:

1、创建线程池

2、线程池对象创建线程执行任务

3、关闭线程池

1、线程池参数

序号

参数名

参数说明

1

corePoolSize

核心线程数

2

maximumPoolSize

最大线程数

3

keepAliveTime

非核心线程空闲状态下线程回收时间

4

unit

keepAliveTime 的时间单位

5

workQueue

任务队列,是一个阻塞队列,当线程数已达到核心线程数,会将任务存储在阻塞队列

6

RejectedExecutionHandler

拒绝策略

ThreadPoolExecutor构造方法:

    public ThreadPoolExecutor(int corePoolSize,

                              int maximumPoolSize,

                              long keepAliveTime,

                              TimeUnit unit,

                              BlockingQueue<Runnable> workQueue,

                              RejectedExecutionHandler handler) {}

2、线程池工作流程

2.1、创建线程池

        int threadNum=11;

int taskNum=10;

        //创建一个自定义线程池对象

        ThreadPoolExecutor  exs = new ThreadPoolExecutor(5, threadNum, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2));

corePoolSize=5       //核心线程数=5

maximumPoolSize=11   //最大线程数=11

keepAliveTime=0      //非核心线程空闲状态下线程回收时间=0

默认拒绝策略:AbortPolicy  //超出后抛弃任务

线程池大小= 最大线程数 + 阻塞队列大小=11+2=13

2.2、线程池对象创建线程执行任务

        for(int i=0;i<taskNum;i++){

            //通过 ExecutorService 对象的 execute 方法将任务添加到线程去执行

            exs.execute(new Runnable1());

            System.out.println("---核心线程数:" + exs.getCorePoolSize()+",线程池中线程数目:"+exs.getPoolSize()+",---队列中等待执行的任务数目:"+ exs.getQueue().size());

        }

threadPoolExecutor 执行 execute 方法分下面4中情况

1)当前线程< coolPoolSize时,直接创建线程执行

当一个任务通过 submit 或者 execute 方法提交到线程池的时候,如果当前池中线程数(包括闲置线程)小于 coolPoolSize,则创建一个线程执行该任务。

2)当前线程>= coolPoolSize时,入队

如果当前线程池中线程数已经达到 coolPoolSize,则将任务放入等待队列。

3) 当前线程>= coolPoolSize,但小于maximumPoolSize时,创建非核心线程执行

如果任务不能入队,说明等待队列已满,若当前池中线程数小于 maximumPoolSize,则创建一个临时线程(非核心线程)执行该任务。

4)如果当前池中线程数已经等于 maximumPoolSize,此时无法执行该任务,根据拒绝执行策略处理。

注意:当池中线程数大于 coolPoolSize,超过 keepAliveTime 时间的闲置线程会被回收掉。回收的是非核心线程,核心线程一般是不会回收的。

如果设置 allowCoreThreadTimeOut(true),则核心线程在闲置 keepAliveTime 时间后也会被回收。

任务队列是一个阻塞队列,线程执行完任务后会去队列取任务来执行,如果队列为空,线程就会阻塞,直到取到任务。

4种拒绝策略RejectedExecutionHandler

  • AbortPolicy:丢弃任务,抛出运行时异常
  • CallerRunsPolicy:由提交任务的线程来执行任务
  • DiscardPolicy:丢弃这个任务,但是不抛异常
  • DiscardOldestPolicy:从队列中剔除最先进入队列的任务,然后再次提交任务

线程池执行任务的流程图:

 

2.3、关闭线程池

exs.shutdown();

线程池有2种关闭方法:

shutdown():线程池拒接收新提交的任务,同时等待线程池里的任务执行完毕后关闭线程池。

shutdownNow() :线程池拒接收新提交的任务,同时立马关闭线程池,线程池里的任务不再执行,并能获取未被执行的任务。

3、示例Demo

  1. package runnable;
  2. import java.util.concurrent.*;
  3. //定义一个 Runnable接口的实现类
  4. class Runnable1 implements Runnable{
  5. @Override
  6. public void run() {
  7. try {
  8. System.out.println(Thread.currentThread().getName()+" 在运行任务");
  9. Thread.sleep(2000);
  10. } catch (InterruptedException e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. }
  15. public class ThreadPoolDemo {
  16. public static void main(String[] args){
  17. int threadNum=9;
  18. int taskNum=10;
  19. //创建一个自定义线程池对象
  20. ThreadPoolExecutor exs = new ThreadPoolExecutor(5, threadNum, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(2));
  21. for(int i=0;i<taskNum;i++){
  22. //通过 ExecutorService 对象的 execute 方法将任务添加到线程去执行
  23. exs.execute(new Runnable1());
  24. System.out.println("---核心线程数:" + exs.getCorePoolSize()+",线程池中线程数目:"+exs.getPoolSize()+",---队列中等待执行的任务数目:"+ exs.getQueue().size());
  25. }
  26. exs.shutdown();
  27. }
  28. }

执行结果分析:

  1. 超过核心线程数,有两个任务入阻塞队列,最后线程1和3执行完成后,这两个任务由线程1和3来执行。
  2. 超过队列数后,创建了非核心线程6,7,8来执行任务。

 参考:https://blog.csdn.net/zhengzhaoyang122/article/details/110789385

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/926037
推荐阅读
相关标签
  

闽ICP备14008679号