java并发编程之ThreadPoolExecutor

记一次java for循环改造多线程的操作 今天在开发质量平台时需要获取某些数据,要请求公司某个工程的OpenAPI接口A。此接口为返回通用数据的接口,且接口本身的RT都在2~3秒之间。使用该接口,需要进行两次循环获取,然后对返回数据进行处理组装,才能得到我这边工程需要的数据。在最开始的时候,我天真的写了两层循环,外层循环为一星期的每一天,内层循环为选取的几个版本号。结果发现整个请求过程(请求接口B和C获取版本相关数据->两层循环请求接口A->数据过滤筛选->数据组装排序)下来,响应时间来到了恐怖的2分钟(🤔要被领导骂死了) 阅读详情


包 java.util.concurrent.*
[ 一 ]、常用线程池 

最常用构造方法为:

ThreadPoolExecutor(int corePoolSize,
                   int maximumPoolSize,
                   long keepAliveTime,
                   TimeUnit unit,
                   BlockingQueue<Runnable> workQueue,

                ThreadFactory threadFactory,

                   RejectedExecutionHandler handler)

 

JDK自带的配置好的线程池:

        // 固定工作线程数量的线程池
        ExecutorService executorService1 = Executors.newFixedThreadPool(3);

        // 一个可缓存的线程池
        ExecutorService executorService2 = Executors.newCachedThreadPool();

        // 单线程化的Executor
        ExecutorService executorService3 = Executors.newSingleThreadExecutor();

        // 支持定时的以及周期性的任务执行
        ExecutorService executorService4 = Executors.newScheduledThreadPool(3);
这些预定义好的线程池服务也是基于ThreadPoolExecutor配置的,所以我们应该从最基本的参数着手了解,如下:

参数详细说明:
[ 1 ]、corePoolSize: 线程池维护线程的最少数量
[ 2 ]、maximumPoolSize:线程池维护线程的最大数量
[ 3 ]、keepAliveTime: 线程池维护线程所允许的空闲时间
[ 4 ]、unit: 线程池维护线程所允许的空闲时间的单位,unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:

  • NANOSECONDS
  • MICROSECONDS
  • MILLISECONDS
  • SECONDS

[ 5]、 workQueue: 线程池所使用的缓冲队列,常用的是:java.util.concurrent.ArrayBlockingQueue 

[6 ]    threadFactory 负责给线程池创建线程的工厂。线程池中的线程是由ThreadFactory创建。如果不特别指定,会使用Executors.defaultThreadFactory创建位于同一个线程组,相同优先级(NORM_PRIORITY)的非守护线程。如果由你来指定ThreadFactory,你可以定制线程名字,线程组,优先级,是否为守护线程等属性。
[ 7 ]、 handler: 线程池对拒绝任务的处理策略,有四个选择如下: 

  • ThreadPoolExecutor.AbortPolicy():抛出java.util.concurrent.RejectedExecutionException异常
  • ThreadPoolExecutor.CallerRunsPolicy():重试添加当前的任务,他会自动重复调用execute()方法
  • ThreadPoolExecutor.DiscardOldestPolicy():抛弃旧的任务
  • ThreadPoolExecutor.DiscardPolicy():抛弃当前的任务

[ 二 ]、详细说明 
[ 1 ]、当一个任务通过execute(Runnable)方法欲添加到线程池时: 

    • 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
    • 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
    • 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
    • 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于 maximumPoolSize,那么通过 handler所指定的策略来处理此任务。也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
    • 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

 

ThreadPoolExecutor的工作机制: 

 

整个ThreadPoolExecutor的任务处理有4步操作:

 

  • 第一步,初始的poolSize < corePoolSize,提交的runnable任务,会直接做为new一个Thread的参数,立马执行
  • 第二步,当提交的任务数超过了corePoolSize,就进入了第二步操作。会将当前的runable提交到一个block queue中
  • 第三步,如果block queue是个有界队列,当队列满了之后就进入了第三步。如果poolSize < maximumPoolsize时,会尝试new 一个Thread的进行救急处理,立马执行对应的runnable任务
  • 第四步,如果第三步救急方案也无法处理了,就会走到第四步执行reject操作。
几点说明:(相信这些网上一搜一大把,我这里简单介绍下,为后面做一下铺垫)
  • block queue有以下几种实现:
    1. ArrayBlockingQueue :  有界的数组队列
    2. LinkedBlockingQueue : 可支持有界/无界的队列,使用链表实现
    3. PriorityBlockingQueue : 优先队列,可以针对任务排序
    4. SynchronousQueue : 队列长度为1的队列,和Array有点区别就是:client thread提交到block queue会是一个阻塞过程,直到有一个worker thread连接上来poll task。
  • RejectExecutionHandler是针对任务无法处理时的一些自保护处理:
    1. Reject 直接抛出Reject exception
    2. Discard 直接忽略该runnable,不可取
    3. DiscardOldest 丢弃最早入队列的的任务
    4. CallsRun 直接让原先的client thread做为worker线程,进行执行
 
容易被人忽略的点:
1.  pool threads启动后,以后的任务获取都会通过block queue中,获取堆积的runnable task.
 
所以建议:  block size >= corePoolSize ,不然线程池就没任何意义
2.  corePoolSize 和 maximumPoolSize的区别, 和大家正常理解的数据库连接池不太一样。
  *  据dbcp pool为例,会有minIdle , maxActive配置。minIdle代表是常驻内存中的threads数量,maxActive代表是工作的最大线程数。
  *  这里的corePoolSize就是连接池的maxActive的概念,它没有minIdle的概念(每个线程可以设置keepAliveTime,超过多少时间多有任务后销毁线程,但不会固定保持一定数量的threads)。 
  * 这里的maximumPoolSize,是一种救急措施的第一层。当threadPoolExecutor的工作threads存在满负荷,并且block queue队列也满了,这时代表接近崩溃边缘。这时允许临时起一批threads,用来处理runnable,处理完后立马退出。
 
所以建议:   maximumPoolSize >= corePoolSize =期望的最大线程数。 (我曾经配置了corePoolSize=1, maximumPoolSize=20, blockqueue为无界队列,最后就成了单线程工作的pool。典型的配置错误)
 
3. 善用blockqueue和reject组合. 这里要重点推荐下CallsRun的Rejected Handler,从字面意思就是让调用者自己来运行。
我们经常会在线上使用一些线程池做异步处理,比如我前面做的 (业务层)异步并行加载技术分析和设计, 将原本串行的请求都变为了并行操作,但过多的并行会增加系统的负载(比如软中断,上下文切换)。所以肯定需要对线程池做一个size限制。但是为了引入异步操作后,避免因在block queue的等待时间过长,所以需要在队列满的时,执行一个callsRun的策略,并行的操作又转为一个串行处理,这样就可以保证尽量少的延迟影响。
 
所以建议:   RejectExecutionHandler = CallsRun ,  blockqueue size = 2 * poolSize (为啥是2倍poolSize,主要一个考虑就是瞬间高峰处理,允许一个thread等待一个runnable任务)
 
 
更多:
http://blog.youkuaiyun.com/waterbig/article/details/4794244
http://rdc.taobao.com/team/jm/archives/595
Java并发编程-ThreadPoolExecutor 线程池 1. 概述 线程池是运用场景最多的并发框架,异步或并发执行的任务都可以使用。 提示:本文根据一些资料学习总结而成,文末有参考链接 2. 使用线程池可带来哪些优点 降低资源消耗: 重复利用已创建的线程,降低线程创建和消费造成的消耗。 提高任务响应速度: 提交任务时,可直接运行,不必等待创建一个新的线程。 提高线程的可管理性: 线程池可对线程进行统一分配、调优和监控,防止无限制创建消耗系统资源、降低系统稳定性。 3. 线程池实现/工作原理 提交新任务到线程池时,线程池的处理流程如下图所.. 阅读详情

相关推荐

Java并发编程系列28:ThreadPoolExecutor自定义拒绝策略(1)

ThreadPoolExecutor自定义策略(1) 首先说下ThreadPoolExecutor的四种拒绝策略 ThreadPoolExecutor.AbortPolicy ThreadPoolExecutor 默认策略 直接抛出java.util.concurrent.RejectedExecutionException异常 ThreadPoolExecutor.DiscardPolicy 丢弃当前任务,但是不抛出异常

fen_fen的专栏 582

Java 多线程

Executors类 newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 newSingleThreadEx...

qq_35939864的博客 330

TMC2209的UART模式详解:如何用串口调试助手配置细分和电流(避坑指南)

本文深入解析TMC2209步进电机驱动器的UART模式,详细讲解如何通过串口调试助手配置细分和电流,包括硬件连接、通信协议、关键寄存器设置及高级功能应用。提供实战避坑指南,帮助开发者优化步进电机控制性能,适用于精密仪器、3D打印等场景。

weixin_29166013的博客 542

Executors基于for循环进行多线程处理

Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务的线程相当于消费者,并用Runnable来表示任务,Executor的实现还提供了对生命周期的支持,以及统计信息收集,应用程序管理机制和性能监视等机制。 1.重点介绍newFixedThreadP...

杨宇 4982

Proteus下载安装快速入门:30分钟掌握全过程

手把手教你完成proteus下载安装,从环境配置到首次运行一气呵成,适合电子设计新手快速掌握仿真工具的核心操作步骤。

weixin_31974443的博客 895

kali2020.2安装出现的问题并附详细解决办法

kali2020.2的安装

weixin_48776804的博客 3050

Java并发之ThreadPoolExecutor

一、ThreadPoolExecutor 简介 ThreadPoolExecutor 是一个可被继承 ( extends ) 的线程池实现,包含了用于微调的许多参数和钩子。主要参数如下: (1) corePoolSize 核心线程数 (2) maximumPoolSize 最大线程数 (3) keepAliveTime 实例化超过 corePoolSize 的线程,在空闲状态下的存活时间 二、Executor实例化 (1) Executors.newSingleThreadExecutor()

ZCC的专栏 504

有关SPSS中Fisher精确检验无法进行的解决方法(由于无法打开临时文件,因此无法进行计算)

最近在帮一个四年生完成她的毕业论文,在用SPSS进行R×C表检验的时候,发现Fisher精确检验的结果无法显示,提示为“由于无法打开临时文件,因此无法进行计算”,大概像下图一样。 (这图是从网上找的) 然...

chuyang37的博客 3万+

Java并发编程之ThreadPoolExecutor构造

表示没有核心线程,线程不会被长期保留。如果任务提交速度超过线程池处理速度,未处理的任务会存放在队列中。,表示只有一个核心线程。,表示线程数可以无限扩展。:空闲线程会在 60 秒后被回收。当线程池无法处理新任务时(队列已满且线程数已达到。,任务直接提交给线程。,表示空闲线程不会被回收。,表示空闲线程不会被回收。时间内没有任务执行,则该线程会被回收。:默认线程工厂,线程名称格式为。:默认线程工厂,线程名称格式为。:默认线程工厂,线程名称格式为。

helloworldcnm的博客 521

跟着团子学SAP CO:揭秘结果分析码在项目结算中的实战应用(一)KKA2/CJ88

本文深入解析了SAP CO模块中结果分析码在项目结算中的核心作用。以KKA2(方法10)和事务代码CJ88为例,详细阐述了如何在项目完工后一次性确认收入的场景下,通过结果分析功能实现收入与成本的精准匹配,将项目成本暂估为在制品,确保各期利润的准确反映。

gamma的博客 687

SWMM建模与案例应用

4、排水系统控制规则通过控制功能,可以在模拟进行过程中,通过条件判断,对闸门、水泵、管道、孔口、堰进行控制,实现排水系统实时控制。5、SWMM与其他模型对比分析分析:STORM、MOUSE、Info Works、SUSTAIN、SWC。1、模型初始设置主要参数:雨量计、汇水区、节点、出水口、管渠、分流器、蓄水池等参数前缀的设置。2、气象数据设置温度、蒸发、风速、融雪、面积亏损、气候调整、雨量计。1、多软件数据交互:CAD、Arcgis、SWMM。(1)节点、管段、水泵、孔口、堰、雨水口和街道。

m0_74575633的博客 3421

Java并发编程之ThreadPoolExecutor线程池源码剖析

  我们开始从 ThreadPoolExecutor 可以做什么来说起,然后进行源码剖析。   ThreadPoolExecutor 的初始化方法为:     public ThreadPoolExecutorLocal(int corePoolSize,                               int maximumPoolSize,                   ...

HappyHeng的博客 467

睿尔曼超轻量仿人机械臂--机械臂接口介绍

本文介绍了睿尔曼超轻量仿人机械臂的控制器接口及末端接口。

realman_Rop的博客 3440

Java并发编程:ThreadPoolExecutor常用线程池

目录 线程池的分类 常用线程池(ThreadPoolExecutor)示例 CachedThreadPool FixedThreadPool SingleThreadExecutor ThreadPoolExecutor类分析 三种线程池(返回ThreadPoolExecutor)构造方法 ThreadPoolExecutor中的成员变量 三种线程池(返回ThreadPoolEx...

Jodness' Blogs 1万+

MATLAB 与 STK 互联的两种连接方式详解

批量仿真推荐使用方法一;交互分析推荐使用方法二。可以根据具体任务灵活切换,也可以同时使用两种方式,提升建模与仿真的效率。

weixin_52370774的博客 1567

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Java并发编程(十八):ThreadPoolExecutor总结与源码深度分析

前言 JUC中包含了很多的工具类,不论是第三方工具包,还是自己开发的业务系统,使用最多的还是是线程池,比如普通的线程池ThreadPoolExecutor、带调度的线程池ScheduledThreadPoolExecutor等,本文就从源码层面探究一下ThreadPoolExecutor的实现原理~ 注:研究线程池源码的目的是为了让自己能够对其有个清晰的认识,理解各个参数设置的含义,以帮助我们正确合理的使用线程池,除非时间非常充足,否则不建议去逐行研究其中的源码,本文也只是分析其核心逻辑的源码~ 总览

黄智霖的博客 4182

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Java并发编程之线程池ThreadPoolExecutor详细介绍

本文主要讲述了线程、协程、线程池,常用的线程池框架,线程池基本原理,核心参数的解释,线程池主要核心方法的源码分析。通过本文可以比较清晰的理解Java中线程池的工作原理机制。

polaris645的专栏 968

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java并发编程之线程池Executors和ThreadPoolExecutor简介

Java线程池原理和正确的使用姿势

polaris645的专栏 294

Java并发编程之美——第八章 Java并发包中线程池ThreadPoolExecutor原理探究

Java并发编程之美——第六章 Java并发包中锁原理剖析 Java并发编程之美——第五章 Java并发包中并发List(CopyOnWriteArrayList)源码剖析 Java并发编程之美——第四章 Java并发包中原子操作类原理剖析 Java并发编程之美——第三章 Java并发包中ThreadLocalRandom类原理剖析 Java并发编程之美——第二章 并发编程的其他知识 Java并发编程之美——第一章 Java并发编程基础 文章目录Time 2022-01-02——Hireek介绍为什么需要线

Hireek的博客 422

Java 并发编程 - ThreadPoolExecutor

(最小线程)、(最大线程)、(空闲回收)、(线程创建);workQueue(任务缓冲)、handler(饱和处理);unit是时间单位辅助参数。合理配置需结合业务场景(如任务执行时长、任务提交频率、是否允许任务丢失),避免“一刀切”(如直接使用可能隐藏 OOM 风险)。

怪味Coding 1060

【java并发编程】ThreadPoolExecutor

一什么是线程池 线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL。 线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。 而本文描述线程池是JDK中提供的ThreadPoolExecutor类。 当然,使用线程池.

worn_xiao的博客 1994

《Java并发编程的艺术》读后笔记-ThreadPoolExecutor详解(第十章)

文章目录《Java并发编程的艺术》ThreadPoolExecutor详解(第十章)1.ThreadPoolExecutor简介2.FixedThreadPool详解3.SingleThreadExecutor详解4.CachedThreadPool详解 《Java并发编程的艺术》ThreadPoolExecutor详解(第十章) 1.ThreadPoolExecutor简介 Executor框架最核心的类是ThreadPoolExecutor,它是线程池的实现类,主要由下列4个组件构成: corePoo

小皮皮LL的博客 559

Java并发编程线程池ThreadPoolExecutor详解

ThreadPoolExecutor的构造方法包含七个关键参数:核心线程数、最大线程数、空闲线程存活时间、时间单位、任务队列、线程工厂及拒绝策略。核心线程数决定池中常驻线程量,而最大线程数限制突发流量下的线程扩容。Java通过ThreadPoolExecutor类提供了高度可配置的线程池实现,允许开发者精细控制线程生命周期、任务队列及拒绝策略。若核心线程满,任务进入队列;掌握ThreadPoolExecutor的细节,不仅能提升程序性能,更能避免资源耗尽导致的系统崩溃,是Java开发者进阶的必备技能。

nqzgha_557的博客 170

Java多线程与并发编程(8)_ThreadPoolExecutor

Java线程池之ThreadPoolExecutor 文章目录Java线程池之ThreadPoolExecutorExecutor体系结构线程池状态构造方法线程池工作方式创建各种线程池提交任务给线程池关闭线程池其他线程池任务调度线程池异常处理 ThreadPoolExecutor是我们使用Java线程池的核心,它所处的体系如下: Executor体系结构 线程池状态 ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量 从数字上比较线程池的终结程

JunsIr的技术栈 2774

Java并发编程-ThreadPoolExecutor

一、核心参数 corePool 核心线程池大小 maximumPool 最大线程池大小 BlockingQueue 工作队列 RejectedExecutionHandler 当Executor已经关闭或饱和,需要拒绝的策略。 二、分类 FixedThreadPool SingleThreadExecutor CachedThreadPool 三、通用Executor执行模型 当前线程数量小于corePoolSize,创建一个新的线程来执行任务 如果线程大于等于corePoolSize,工作队列不

u013551615的博客 193
上一篇: 修改my.cnf文件导致mysql启动不了的问题
下一篇: Ajax跨域问题研究笔记
zljjava
博客等级 码龄15年 155粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值