线程数

线程池源码解析

早过忘川 提交于 2020-02-26 11:55:17
前言   Java提供了若干种线程池,常用的线程池是ThreadPoolExecutor,其中用于提交任务的方法是execute以及submit方法,其中submit最终也是会调用execute方法,所以这里只介绍excute及其相关方法。   在介绍源码之前,希望读者对于线程池参数有基本了解会有助于理解代码,可以查看这篇文章 https://juejin.im/post/5cae9b42f265da03705fa152 。 主要成员变量 1 // 线程池状态量,高3未用于表示线程池运行状态,低29位用于表示线程池的线程数 2 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); 3 private static final int COUNT_BITS = Integer.SIZE - 3; 4 // 线程池最大容量,这里是程序硬性规定的最大数量,优先级高于maximumPoolSize 5 private static final int CAPACITY = (1 << COUNT_BITS) - 1; 6 7 // 线程池运行状态 8 private static final int RUNNING = -1 << COUNT_BITS; 9 private static final

关于线程池

情到浓时终转凉″ 提交于 2020-02-24 13:35:09
线程池的核心参数 corePoolSize: 核心池的大小。在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建线程去执行任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一个线程。默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; maximumPoolSize: 线程池最大线程数,这个参数也是一个非常重要的参数,它表示在线程池中最多能创建多少个线程; keepAliveTime: 表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法

Java并发包——线程池

北慕城南 提交于 2020-02-24 13:33:05
Java并发包——线程池 摘要:本文主要学习了Java并发包中的线程池。 部分内容来自以下博客: https://www.cnblogs.com/dolphin0520/p/3932921.html https://blog.csdn.net/luzhen1012/article/details/79230091 https://www.cnblogs.com/wxgblogs/p/5469208.html https://blog.csdn.net/seasonLai/article/details/82624236 https://www.jianshu.com/p/7b1546a3b85b 线程池相关类和接口 Executor Executor是一个顶层接口,在它里面只声明了一个execute方法,返回值为void,参数为Runnable类型。 该方法用来在接下来的某个时刻执行提交的command任务。由于Executor不同的实现,执行的时候可能在一个新线程中或由一个线程池里的线程执行,还可以是由调用者线程执行。 1 public interface Executor { 2 void execute(Runnable command); 3 } ExecutorService ExecutorService接口继承了Executor接口,并声明了一些方法。 1

池化技术——自定义线程池

柔情痞子 提交于 2020-02-23 11:17:03
目录 池化技术——自定义线程池 1、为什么要使用线程池? 1.1、池化技术的特点: 1.2、线程池的好处: 1.3、如何自定义一个线程池 2、三大方法 2.1、单个线程的线程池方法 2.2、固定的线程池的大小的方法 2.3、可伸缩的线程池的方法 2.4、完整的测试代码为: 3、为什么要自定义线程池?三大方法创建线程池的弊端分析 4、七大参数 5、如何手动的去创建一个线程池 6、四种拒绝策略 6.1、会抛出异常的拒绝策略 6.2、哪来的去哪里拒绝策略 6.3、丢掉任务拒绝策略 6.4、尝试竞争拒绝策略 7、关于最大线程数应该如何确定 7.1、CPU密集型 7.2、IO密集型 7.3、公式总结 池化技术——自定义线程池 1、为什么要使用线程池? 池化技术 1.1、池化技术的特点: 程序的运行,本质:占用系统的资源! 优化资源的使用!=>池化技术 线程池、连接池、内存池、对象池///..... 创建、销毁。十分浪费资源 池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。 1.2、线程池的好处: 降低资源的消耗 降低资源的消耗 方便管理。 核心:==线程复用、可以控制最大并发数、管理线程== 1.3、如何自定义一个线程池 牢记:==三大方法、7大参数、4种拒绝策略== 2、三大方法 三大方法 在java的JDK中提够了Executors开启JDK默认线程池的类

服务性能优化过程

浪尽此生 提交于 2020-02-22 15:11:23
背景 组内有好几个线上服务,除了业务逻辑不一样,请求处理过程基本上都是一致的。这些服务的执行逻辑都非常简单,但是有几个问题: 单机QPS很低,需要很多台机器 99分位耗时比理论上的长很多 在服务的负载达到上限时,服务器的负载却非常低 上面的这些问题在财大气粗的公司面前都不是问题啊,性能不够加机器! 性能不够加机器! 上游再一次过来反映超时问题时,为了壮年程序员的尊严,这次刚好有时间决定不再单纯的加机器,要把这个程序优化一下,用一次屠龙技。 技术栈: 语言:java 通信方式:thrift,server模式为THsHaServer redis客户端:jedis 模型:xgboost 执行环境:docker,8核 8G 缓存集群:通信协议为redis,但实现方式和redis不一样 优化后结果 优化过程 想要提升程序的性能,首先需要找到程序的瓶颈所在,然后有针对的去进行优化。 流程分析 优化前流程图 这个流程图省略了业务处理逻辑,只展示了各个线程之间的交互关系。构造redis请求的那部分逻辑,其实使用了两个forkjoin线程池,但它们两个的逻辑非常类似,为了简化把它们合并到一个流程中了。流程图中有两个深红色的步骤,很明显的看出两个明显能影响性能的地方。 结合服务的执行环境,可以总结出以下问题: 线程数过多 由于操作系统对线程的抢占式调度,线程频繁的上下文切换会带来几个问题:

并发编程之线程池

好久不见. 提交于 2020-02-20 10:57:08
并发编程之线程池 4. 自定义线程池 ThreadPoolExecutor 异步模式之工作线程 3. Fork/Join 4. 自定义线程池 步骤1 :自定义拒绝策略接口 ThreadPoolExecutor 1)线程池状态 ThreadPoolExecutor使用int的高3位来表示线程池状态,低29位表示线程数量 从数字上比较,TERMINATED>TIDYING>STOP>SHUTDOWN>RUNNING 这些信息存储在一个原子变量ctl中目的是将线程池状态与线程个数合二为一,这样就可以用一次cas原子操作进行赋值 2)构造方法 corePool :Size核心线程数目(最多保留的线程数) maximunPoolSize :最大线程数目 keepAliveTIme :生存时间- 针对救急线程 unit :时间单位 - 针对救急线程 workQueue :阻塞队列 threadFactory :线程工厂 - 可以为线程创建时起个好名字 handler :拒绝策略 工作方式 : 线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务。 当线程数达到corePoolSize并没有线程空闲,这时再加入任务,新加的任务会被加入workQueue队列排队,直到有空闲的线程。 如果队列选择了有界队列,那么任务超过了队列大小时,会创建maximumPoolSize

并发编程之线程池

孤者浪人 提交于 2020-02-20 10:17:08
并发编程之线程池 4. 自定义线程池 ThreadPoolExecutor 异步模式之工作线程 3. Fork/Join 4. 自定义线程池 步骤1 :自定义拒绝策略接口 ThreadPoolExecutor 1)线程池状态 ThreadPoolExecutor使用int的高3位来表示线程池状态,低29位表示线程数量 从数字上比较,TERMINATED>TIDYING>STOP>SHUTDOWN>RUNNING 这些信息存储在一个原子变量ctl中目的是将线程池状态与线程个数合二为一,这样就可以用一次cas原子操作进行赋值 2)构造方法 corePool :Size核心线程数目(最多保留的线程数) maximunPoolSize :最大线程数目 keepAliveTIme :生存时间- 针对救急线程 unit :时间单位 - 针对救急线程 workQueue :阻塞队列 threadFactory :线程工厂 - 可以为线程创建时起个好名字 handler :拒绝策略 工作方式 : 线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务。 当线程数达到corePoolSize并没有线程空闲,这时再加入任务,新加的任务会被加入workQueue队列排队,直到有空闲的线程。 如果队列选择了有界队列,那么任务超过了队列大小时,会创建maximumPoolSize

自定义线程池影响的线上事故

家住魔仙堡 提交于 2020-02-18 22:32:24
  作为一个牛逼的程序员,相信大家肯定是接触过多线程的概念的。并且可能会在实际的工作中因为一些业务场景需要使用自定义线程池来执行批量的任务或对线程进行管理。同样,我们项目中也存在一个两个场景需要使用线程池。而这两个场景分别为: 1、持续监听某个外部接口的不间断的返回信息,其实就是长链接的阻塞接口,总共12种资源需要监听,所以就意味需要12个不间断的线程执行阻塞任务。 2、RabbitMQ的消费者,因为需要应用启动的时候就执行消息的消费,所以也通过线程池中获取线程执行消费任务。 一、先看线程池的定义 public class ThreadPoolUtil { private static Logger logger = LoggerFactory.getLogger(ThreadPoolUtil.class); private static volatile ThreadPoolExecutor threadPoolExecutor = null; /** * 创建 * @return */ private static AtomicInteger nextId = new AtomicInteger(0); public static ThreadPoolExecutor createExecutor(){ int corePoolSize = 12; // 核心线程12个 int

java基础加强

陌路散爱 提交于 2020-02-17 22:57:44
java程序的执行过程 编写java程序 编写完的java程序,进行保存时自动将.java文件编译成.class文件 先启动虚拟机,虚拟机加载字节码对象.class文件,进行这个类的main方法开始执行 数据类型 基本数据类型 类型 描述 byte 占1个字节,范围-127-128,-2 7 到2 7 -1 short 占2个字节,范围-2 15 到2 15 -1 int 占4个字节,范围-2 31 到2 31 -1 long 占8个字节,范围-2 63 到2 63 -1 float 占4个字节,单精度 double 占8字节,双精度度 char 占2字节 boolean 占1字节 引用数据类型 基本类型的字面值规则 整数的字面值是int类型 byte、short、char三种比int小的整数,可以用范围内的值可以直接赋值 浮点数字字面值,是double类型 字面值的后缀:L表示long,F表示float,D表示double类型 字面值的前缀:0b表示二进制,0表示八进制,0x表示十六进制,\u表示char16机制 基本类型的运算规则 计算结果的数据类型,和算项的最大类型保持一致 byte、short、char三种比int小的整数,运算时自动转化成int 整数运算溢出 浮点数计算不精确 浮点数的特殊值: Java基础 1.验证JDK是否安装成功的命令: Echo %JAVA

ThreadPoolExecutor简单理解与使用

一世执手 提交于 2020-02-17 14:42:57
查看ThreadPoolExecutor的源码发现,其提供了4个构造方法,如下: 其中典型使用 线程池会根据corePoolSize和maximumPoolSize自动地调整线程池大小 如果当前线程池的线程数少于corePoolSize线程正在运行的个数时, 无论已有线程是否空闲,都会新增一个线程 如果当前线程池的线程大于或者是等于corePooleSIze,并且任务队列没有满时,将其提交给阻塞队列排队 如果线程池的大于或者等于corePoolSize,并且任务队列满时 如果当前线程池的线程 < maximumPoolSize,则新增线程 如果当前线程池的线程 = maximumPoolSize, 拒绝新增任何,可通过拒绝策略来进行控制 任务执行过程: 1. 提交新的任务时,判断,是否达到了核心线程数量,如果达到,则创建一个工作线程来执行任务 2. 判断工作队列是否已经满了, 如果没满,则将新提交的任务存储在工作队列中 3. 判断是否达到了线程最大数量,如果没有达到, 则创建一个新的工作线程来执行 4. 通过拒绝策略来处理任务 Executors常用工具类: newFixedThreadPool(int nThreads): 固定大小,任务队列容量无界的线程池.corePoolSize=maximumPoolSize。 newCachedThreadPool():