详解Java线程池的使用及工作原理

 更新时间:2021年05月28日 16:30:27   作者:小海子l  
在日常开发过程中总是以单线程的思维去编码,没有考虑到在多线程状态下的运行状况.由此引发的结果就是请求过多,应用无法响应.为了解决请求过多的问题,又衍生出了线程池的概念.本文记录了Java中线程池的使用及工作原理,需要的朋友可以参考下

一、什么是线程池?

线程池是一种用于实现计算机程序并发执行的软件设计模式。线程池维护多个线程,等待由调度程序分配任务以并发执行,该模型提高了性能,并避免了由于为短期任务频繁创建和销毁线程而导致的执行延迟。

二、线程池要解决什么问题?

说到线程池就一定要从线程的生命周期讲起。

在这里插入图片描述

从图中可以了解无论任务执行多久,每个线程都要经历从生到死的状态。而使用线程池就是为了避免线程的重复创建,从而节省了线程的NewRunnableRunningTerminated的时间;同时也会复用线程,最小化的节省系统资源,于此同时提高了响应速度。

三、线程池的使用

线程池的创建

使用ThreadPoolExecutor并配置7个参数完成线程池的创建

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
  • corePoolSize:线程池中核心线程的最大值
  • maximumPoolSize:线程池中最大线程数
  • keepAliveTime:非核心线程空闲的存活时间大小
  • unit:keepAliveTime的单位,常用的有秒、分钟、小时等
  • workQueue:阻塞队列类型
  • threadFactory:线程工厂,用于配置线程的名称,是否为守护线程等
  • handler:线程池的拒绝策略

四、常用阻塞队列

ArrayBlockingQueue

底层基于数组的实现的有界阻塞队列

LinkedBlockingQueue

底层基于单链表的阻塞队列,可配置容量,不配置容量默认为Integer.MAX_VALUE

五、线程工厂

《阿里巴巴Java开发手册》中强制要求指定线程的名称

在这里插入图片描述

由于工作是使用hutool比较多,里面也包含对ThreadFactory的封装,可以很方便的指定名称

ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();

六、拒绝策略

当线程池内工作线程数大于maximumPoolSize时,线程就不再接受任务,执行对应的拒绝策略;目前支持的拒绝策略有四种:

1.AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常

2.CallerRunsPolicy:由调用者处理

3.DiscardOldestPolicy:丢弃队列中最前面的任务,并重新入队列

4.DiscardPolicy:丢弃任务但不抛出异常

七、线程池的执行逻辑

// 创建线程工厂
ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();
// 创建线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), threadFactory, new ThreadPoolExecutor.AbortPolicy());

八、execute()方法

// 组合值;保存了线程池的工作状态和工作线程数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
public void execute(Runnable command) {
    	// 任务为空 抛出NPE
        if (command == null)
            throw new NullPointerException();
        // 获取线程池状态
        int c = ctl.get();
        // 如果工作线程数小于核心线程数就创建新线程
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        // 如果线程池处于Running状态,就把任务放在队列尾部
        if (isRunning(c) && workQueue.offer(command)) {
            // 重新检查线程池状态
            int recheck = ctl.get();
            // 如果线程池不是Running状态,就移除刚才添加的任务,并执行拒绝策略
            if (! isRunning(recheck) && remove(command))
                reject(command);
            // 是Running状态,就添加线程
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        // 添加任务失败,执行拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }
// addWorker()完成线程的创建

九、执行流程

在这里插入图片描述

到此这篇关于详解Java线程池的使用及工作原理的文章就介绍到这了,更多相关Java线程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java和MySQL数据库中关于小数的保存问题详析

    Java和MySQL数据库中关于小数的保存问题详析

    在Java和MySQL中小数的精度可能会受到限制,如float类型的小数只能精确到6-7位,double类型也只能精确到15-16位,这篇文章主要给大家介绍了关于Java和MySQL数据库中关于小数的保存问题,需要的朋友可以参考下
    2024-01-01
  • java 代码块与静态代码块加载顺序

    java 代码块与静态代码块加载顺序

    这篇文章主要介绍了java 代码块与静态代码块加载顺序的相关资料,需要的朋友可以参考下
    2017-07-07
  • Java8 日期、时间操作代码

    Java8 日期、时间操作代码

    在Java8之前,日期时间API一直被开发者诟病,包括:java.util.Date是可变类型,SimpleDateFormat非线程安全等问题。故此,Java8引入了一套全新的日期时间处理API,新的API基于ISO标准日历系统
    2021-09-09
  • springcloud feign 接口指定接口服务ip方式

    springcloud feign 接口指定接口服务ip方式

    这篇文章主要介绍了springcloud feign 接口指定接口服务ip方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • SpringBoot路径映射实现过程图解

    SpringBoot路径映射实现过程图解

    这篇文章主要介绍了SpringBoot路径映射实现过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • Java并发编程之详解ConcurrentHashMap类

    Java并发编程之详解ConcurrentHashMap类

    在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口,本文为系列文章第八篇.需要的朋友可以参考下
    2021-06-06
  • springboot 集成cas5.3 实现sso单点登录详细流程

    springboot 集成cas5.3 实现sso单点登录详细流程

    SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。单点登录是目前比较流行的企业业务整合的解决方案之一,本文给大家介绍springboot 集成cas5.3 实现sso单点登录功能,感兴趣的朋友一起看看吧
    2021-10-10
  • springboot中request和response的加解密实现代码

    springboot中request和response的加解密实现代码

    这篇文章主要介绍了springboot中request和response的加解密实现,在springboot中提供了RequestBodyAdviceAdapter和ResponseBodyAdvice,利用这两个工具可以非常方便的对请求和响应进行预处理,需要的朋友可以参考下
    2022-06-06
  • IDEA连接Mysql数据库的详细图文教程

    IDEA连接Mysql数据库的详细图文教程

    项目开发时使用Intellij IDEA连接本地数据库,将数据库可视化,还可对数据库表直接进行增删改查操作,方便快捷又清晰,下面这篇文章主要给大家介绍了关于IDEA连接Mysql数据库的详细图文教程,需要的朋友可以参考下
    2023-03-03
  • springboot中请求路径配置在配置文件中详解

    springboot中请求路径配置在配置文件中详解

    这篇文章主要介绍了springboot中请求路径配置在配置文件中,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01

最新评论