热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ThreadPoolExecutor源码学习(一)核心属性及应用

在Executors类中,jdk提供了四个线程池可以使用,分别是newCachedThreadPool:corePoolSize是0&#x

在Executors类中,jdk提供了四个线程池可以使用,分别是
newCachedThreadPool:
corePoolSize是0,允许创建的最大线程数量是Integer.MAX_VALUE
newScheduledThreadPool:
允许创建的最大线程数量是Integer.MAX_VALUE
newFixedThreadPool:
任务队列允许的最大长度是Integer.MAX_VALUE
newSingleThreadExecutor:
任务队列允许的最大长度是Integer.MAX_VALUE

这四种是阿里巴巴Java开发规范中所不推荐的,因为这四个线程池中,要么是最大线程数无界,要么阻塞队列无界,可能会造成OOM

推荐使用自定义的线程池,这样可以合理控制最大线程数和阻塞队列以及拒绝策略等

ThreadPoolExecutor中有几个重要的属性


自定义线程池

private static void customThreadPool() {ExecutorService threadPool &#61; new ThreadPoolExecutor(2, 5, 1L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());try {for (int i &#61; 0; i < 90; i&#43;&#43;) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName() &#43; "\t 开始处理业务");});}} catch (Exception e) {e.printStackTrace();} finally {threadPool.shutdown();}}

参数说明


核心属性

int corePoolSize&#xff1a;核心线程数
int maximumPoolSize&#xff1a;允许创建的最大线程数
long keepAliveTime&#xff1a;空闲时间
TimeUnit unit&#xff1a;时间单位
BlockingQueue<Runnable> workQueue&#xff1a;任务队列
ThreadFactory threadFactory&#xff1a;线程池工厂
RejectedExecutionHandler handler&#xff1a;拒绝策略对于一个线程池来说&#xff0c;允许有 maximumPoolSize &#43; workQueue.length 个任务提交过来&#xff0c;超过了这个阈值&#xff0c;就会触发拒绝策略private final AtomicInteger ctl &#61; new AtomicInteger(ctlOf(RUNNING, 0));
这个遍历的高三位保存的是线程池的状态&#xff0c;后29位保存的是线程池中工作线程的数量

线程池状态

/*** 运行状态&#xff0c;线程池刚创建就是这个状态* 高三位是111&#xff0c;低29位是0* 该状态会接收新的任务请求* 也会处理在阻塞队列中等待处理的任务*/private static final int RUNNING &#61; -1 << COUNT_BITS;/*** 停工状态&#xff0c;不再接收新任务&#xff0c;但是会处理已经在执行的和阻塞队列中的任务* 高三位为000&#xff0c;低29位为0&#xff0c;* 在running状态调用线程池的shutdown()方法&#xff0c;会从running变更为shutdown*/private static final int SHUTDOWN &#61; 0 << COUNT_BITS;/*** 停止状态&#xff0c;不再接收新任务&#xff0c;已有的任务也会中断,阻塞队列中的任务也不会再运行* 高三位为001&#xff0c;低29位为0* 在调用shutdownnow()方法之后&#xff0c;会从running/shutdown变更为stop状态*/private static final int STOP &#61; 1 << COUNT_BITS;/*** 清空状态&#xff0c;所有任务都停止了&#xff0c;工作的线程也全部结束了&#xff0c;workerCount为0* 高三位为010&#xff0c;低29位为0* 为此状态时&#xff0c;还将调用terminated()方法*/private static final int TIDYING &#61; 2 << COUNT_BITS;/*** 终止状态&#xff0c;线程池已经销毁&#xff1b;为此状态时还将调用terminated()方法* 高三位为100&#xff0c;低29位为0*/private static final int TERMINATED &#61; 3 << COUNT_BITS;

拒绝策略&#xff1a;

1、AbortPolicy&#xff1a;直接抛出异常 RejectedExecutionException
2、CallerRunsPolicy&#xff1a;在调用方线程中执行任务
3、DiscardOldestPolicy&#xff1a;丢弃最先进入到队列中的任务&#xff0c;调用的是queue.offer()方法
4、DiscardPolicy&#xff1a;不做任务处理&#xff0c;其实丢弃的是当前任务

运行原理

1. 创建线程池&#xff0c;等待请求过来2. 当调用了execute()方法添加一个请求任务之后&#xff0c;线程池会做如下判断:3. 1. 如果当前运行的线程数小于corePoolSize&#xff0c;那么会创建线程&#xff0c;运行这个任务2. 如果正在运行的线程数量大于或者等于corePoolSize,那么将这个任务加入队列3. 如果队列也满了&#xff0c;这时候运行的线程数还小于maximumPoolSize&#xff0c;就会创建非核心线程来运行这个任务4. 如果队列满了&#xff0c;且正在运行的线程数达到了maximumPoolSize,那么线程池会启动拒绝策略来执行4. 当一个线程的任务结束之后&#xff0c;会从队列中取下一个任务来执行5. 当一个线程空闲时间超过了keepAliveTime时&#xff0c;线程池会做以下判断:6. 如果当前运行的线程数超过了corePoolSize时&#xff0c;那么这个线程会被销毁&#xff0c;线程池中所有任务结束以后&#xff0c;线程数量会缩减到corePoolSize的大小

execute和submit的区别

1.入参不同&#xff0c;execute的入参只能是Runnable,submit的入参可以是Runnable&#xff0c;也可以是callable
2.submit有返回值&#xff0c;submit底层也是调用的execute&#xff0c;在调用execute的时候&#xff0c;会把入参包装成RunnableFuture
3.submit方便异常处理&#xff0c;如果task抛出了异常&#xff0c;那么通过future.get()可以捕获到异常信息


核心方法

在这里插入图片描述

1.Executor是线程池的基本接口&#xff0c;只有一个execute方法
2.ExecutorService是线程池Executor接口的子接口&#xff0c;额外提供了一些对线程池的其他操作&#xff1a;submit、shutdown等
3.AbstractExecutorService抽象类&#xff0c;实现了executorService的部分接口&#xff0c;比如&#xff1a;submit
4.ThreadPoolExecutor继承了AbstractExecutorService


获取线程池状态、工作线程数量

/*** 获取当前线程池的状态* &#64;param c* &#64;return*/private static int runStateOf(int c) { return c & ~CAPACITY; }/*** 获取线程池活跃的数量* &#64;param c* &#64;return*/private static int workerCountOf(int c) { return c & CAPACITY; }/*** 获取运行状态和活动线程数量的值* &#64;param rs* &#64;param wc* &#64;return*/private static int ctlOf(int rs, int wc) { return rs | wc; }

runWorker()

执行提交的任务&#xff0c;这是比较核心的方法&#xff0c;在该方法中
1、先执行当前提交的任务
2、从任务队列中获取排队的任务
3、并执行


getTask()

这是从任务队列中获取排队任务的方法&#xff0c;在新增一个线程的时候&#xff0c;会先执行当前提交的任务&#xff0c;如果该任务执行完了之后&#xff0c;会从任务队列中尝试获取正在排队的任务&#xff0c;去依次执行


推荐阅读
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文介绍了如何通过配置 Android Studio 和 Gradle 来显著提高构建性能,涵盖内存分配优化、并行构建和性能分析等实用技巧。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • 本文详细介绍如何使用Samba软件配置CIFS文件共享服务,涵盖安装、配置、权限管理及多用户挂载等关键步骤。通过具体示例和命令行操作,帮助读者快速搭建并优化Samba服务器。 ... [详细]
author-avatar
zhenhuaYang
编程、骑行、健身、民谣、生活!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有