Hi,运维,你懂Java吗--No.9:线程池

news2024/10/7 8:20:48

        作为运维,你不一定要会写Java代码,但是一定要懂Java在生产跑起来之后的各种机制。

        本文为《Hi,运维,你懂Java吗》系列文章 第九篇,敬请关注后续系列文章

        欢迎关注 龙叔运维(公众号) 持续分享运维经验

前言

        本篇对java的线程池进行讲解,线程池对java应用的性能来说有很重要的影响。

1、什么是线程池

        类似数据库连接池,主要是为了避免线程不断创建销魂造成的大量资源消耗。

        线程池按照设定管理线程。控制运行的线程的数量,将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量超出数量的线程排队等候,等其它线程执行完毕, 再从队列中取出任务来执行。主要特点为:线程复用;控制最大并发数;管理线程。

【线程池的处理流程】

 

如上图,有几个概念,下面进行简单讲解:

a、核心线程:核心线程是在空闲时也不会被回收的线程,可以说是常驻线程,数量由corePoolSize参数控制

b、非核心线程:当核心线程都在处理任务,阻塞队列也满了的情况下,有任务进来,当前线程数没有达到maximumPoolSize参数设置的最大值的时候,就会创建新的线程处理队列中的任务,这些非核心线程不是常驻的,空闲时间超过keepAliveTime 参数设置的时间(时间单位由unit 参数设置)就会被回收

c、阻塞队列/工作队列:核心线程数满之后,新进入的任务加入到队列中等待被执行,队列也有四种,由workQueue参数设置,下面会单独讲解

d、拒绝策略:当阻塞队列满,且线程数已达到最大线程数限制,就会执行拒绝策略,拒绝策略也有四种,由handler参数设置,下面会单独讲解

2、线程池配置

创建线程池的时候一共有7个参数:

a、corePoolSize:核心线程数

b、maximumPoolSize:最大线程数

c、keepAliveTime:非核心线程的最大空闲时间(为0表示非核心线程空闲就立即回收),只有当线程池中的线程数大于corePoolSize时keepAliveTime才会起作用,直到线程中的线程数不大于corepoolSIze。

d、unit:时间单位,作用于keepAliveTime,

e、threadFactory:线程工厂,可以设置线程名,是否为守护线程等

f、workQueue:阻塞队列

g、handler:拒绝策略

 

如下为线程池创建代码:

public ExecutorService executorService(){
    return new ThreadPoolExecutor(
            POLLER_THREAD_COUNT,
            POLLER_THREAD_COUNT * 8,
            10L,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(64),
            new ThreadFactoryBuilder().setNameFormat("AppName_FutureTask-%d").setDaemon(true).build(),
            new ThreadPoolExecutor.CallerRunsPolicy());
}

3、线程池状态

(1)RUNNING:线程池创建之后的初始状态,这种状态下可以执行任务。

(2)SHUTDOWN:该状态下线程池不再接受新任务,但是会将工作队列中的任务执行完毕。

(3)STOP:该状态下线程池不再接受新任务,也不会处理工作队列中的剩余任务,并且将会中断所有工作线程。

(4)TIDYING:该状态下所有任务都已终止或者处理完成,将会执行terminated()钩子方法。

(5)TERMINATED:执行完terminated()钩子方法之后的状态。terminated钩子方法在Executor终止时调用,默认实现不执行任何操作
 

 

4、常见线程池

线程池描述corePoolSizemaximumPoolSizekeepAliveTime阻塞队列
FixedThreadPool创建指定数量线程,且线程一直存在,阻塞队列很大创建时传参和corePoolSize一样0

无界队列

LinkedBlockingQueue

CachedThreadPool没有常驻线程,根据需要增加和减少,使用无容量的同步阻塞队列0Integer.MAX_VALUE60秒

同步队列

SynchronousQueue

ScheduledThreadPool该线程池用于执行定时任务和周期性任务。可以指定线程池中的线程数量。创建时传参Integer.MAX_VALUE0

无界队列(延迟、排序)

DelayedWorkQueue

SingleThreadExecutor该线程池只会创建一个线程,用于执行所有的任务。110

无界队列

LinkedBlockingQueue

SingleThreadScheduledExecutor一个可以周期性执行任务的单线程线程池1Integer.MAX_VALUE0

无界队列(延迟、排序)

DelayedWorkQueue

5、阻塞队列

常用阻塞队列有四种,应该根据业务场景选择合适的

a、ArrayBlockingQueue

一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。创建其对象必须明确大小,像数组一样。

b、LinkedBlockingQueue

一个可改变大小的阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。创建其对象如果没有明确大小,默认值是Integer.MAX_VALUE。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低。 

Integer.MAX_VALUE表示:int 数据类型的最大值,即:2147483647

c、PriorityBlockingQueue

类似于LinkedBlockingQueue,但其所含对象的排序不是FIFO,而是依据对象的自然排序顺序或者是构造函数所带的Comparator决定的顺序。

d、SynchronousQueue

同步队列。同步队列没有任何容量,往队列中插入数据之后,不能立即返回,必须等待另一个线程将数据处理掉,才会返回,相当于将放入数据到队列的这个线程阻塞住了。

这个使用场景是比较少的,使用SynchronousQueue阻塞队列一般要求maximumPoolSizes为无界,避免线程拒绝执行操作。

 

e、DelayQueue

具有延迟的功能,我们可以设定在队列中的任务延迟多久之后执行。它是无界队列,但是放入的元素必须实现Delayed接口,而Delayed接口又继承了Comparable接口,所以自然就拥有了比较和排序的能力.

6、拒绝策略

线程数已经达到最大线程数,阻塞队列也满了,就会执行拒绝策略,java有下面四个策略,当然也可以自定义策略

  • AbortPolicy:直接抛出 RejectedExecutionException 异常,影响系统运行
  • CallerRunsPolicy:用调用者所在线程(提交任务的线程)来执行任务
  • DiscardOldestPolicy:丢弃任务队列里最早的任务,把提交的任务加入任务队列
  • DiscardPolicy:直接丢弃提交的任务。【如果允许丢弃任务,这就是最好的处理方式】

7、线程池常见异常

7.1、线程池过载

     线程池过载是指线程数量过多造成服务器资源使用过高,降低系统性能

    1、系统性能下降

    2、服务器内存过高,深圳OOM

异常分析:

    1、任务对象过多:线程数达到最大线程数限制,阻塞队列使用的是无界队列,并发持续很高的情况下,线程处理不过来,队列不断新增任务,导致内存撑爆

    2、线程过多,线程数无限制(最大限制为Integer.MAX_VALUE),高并发任务情况下,不断创建线程处理任务,增加服务器资源消耗,如内存,线程栈不断增多,撑爆内存

异常处理:

    1、重启快速恢复(但可能很快继续异常)

    2、使用核实的阻塞队列,设置核实的线程数最大限制,使用合理的拒绝策略

7.2、线程池阻塞

   线程池阻塞是指当线程池中的线程数量达到最大值时,新的任务会被阻塞,导致程序性能下降

    java.util.concurrent.RejectedExecutionException

异常分析:

    一般触发这个报错的时候,就是线程已经达到最大线程限制,且阻塞队列已满,新的任务无法处理

异常处理:

    1、使用合理的拒绝策略,如果是可以忽略的任务,使用丢弃方式是最好的

    2、调整阻塞队列大小,但是要适当,避免过高并发不断创建任务到队列导致内存OOM。

    3、根据业务情况,如果可以异步提交,可以创建任务后就返回,不阻塞提交任务的线程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/842291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

8个最高效的Python爬虫框架,你用过几个?

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 小编收集了一些较为高效的Python爬虫框架。分享给大家。 1.Scrapy Scrapy是一个为了爬取网站数据&#xff0c;提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘&#xff0c;信息处理或存储历史数据等一系列的程…

Springboot @Validated注解详细说明

在Spring Boot中&#xff0c;Validated注解用于验证请求参数。它可以应用在Controller类或方法上 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId> </depen…

SpringBoot源码分析(7)--prepareContext/准备应用上下文

文章目录 一、前言二、prepareContext2.1、context.setEnvironment2.2、postProcessApplicationContext(context);2.3、applyInitializers(context)2.4、发布ApplicationContextInitializedEvent事件2.5、打印启动和profile日志2.6、注册单例Bean2.6.1、手工注册单例Bean流程 2…

尚品汇总结七:商品详情模块(面试专用)

一、业务介绍 订单业务在整个电商平台中处于核心位置&#xff0c;也是比较复杂的一块业务。是把“物”变为“钱”的一个中转站。 整个订单模块一共分四部分组成&#xff1a; 结算页面 在购物车列表页面中,有一个结算的按钮,用户一点击这个按钮时,跳转到结算页,结算页展示了用…

单细胞测序基础知识

构建文库 上机测序 根据不同的荧光检测不同的碱基 质量控制&#xff08;质控QC&#xff09; 去除低质量的序列 表达定量 统计reads数&#xff0c;进而得到表达矩阵 标准化 让所有样本处在同一起跑线上 主成分分析PCA 图中每个点都代表一个样本&#xff0c;不同颜色…

【Linux】网络套接字知识点补足

目录 1 地址转换函数 1.1 字符串转in_addr的函数: 1.2 in_addr转字符串的函数: 1.3 关于inet_ntoa 2 TCP协议通讯流程 1 地址转换函数 本节只介绍基于IPv4的socket网络编程,sockaddr_in中的成员struct in_addr sin_addr表示32位 的IP 地址但是我们通常用点分十进制的字符串…

[BabysqliV3.0]phar反序列化

文章目录 [BabysqliV3.0]phar反序列化 [BabysqliV3.0]phar反序列化 开始以为是sql注入 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ST1jvadM-1691302941344)(https://raw.githubusercontent.com/leekosss/photoBed/master/202308032140269.png)…

CentOS 7中,配置了Oracle jdk,但是使用java -version验证时,出现的版本是OpenJDK,如何解决?

1.首先&#xff0c;检查已安装的jdk版本 sudo yum list installed | grep java2.移除、卸载圈红的系统自带的openjdk sudo yum remove java-1.7.0-openjdk.x86_64 sudo yum remove java-1.7.0-openjdk-headless.x86_64 sudo yum remove java-1.8.0-openjdk.x86_64 sudo yum r…

java.util.NoSuchElementException: No value present-报错(已解决)

阿丹&#xff1a; 今天在spring-boot整合MongoDB的过程中出现了下面的错误&#xff0c;是因为追求新技术、更优雅产生的。 记录一下。 错误截图如下&#xff1a; 错误位置代码如下&#xff1a; 主要问题&#xff08;问题原因&#xff09;&#xff1a; 因为之前升级了我的jdk的…

Java基础——注解

1 概述 注解用于对Java中类、方法、成员变量做标记&#xff0c;然后进行特殊处理&#xff0c;至于到底做何种处理由业务需求来决定。 例如&#xff0c;JUnit框架中&#xff0c;标记了注解Test的方法就可以被当做测试方法进程执行 2 自定义注解 public interface 注解名称 {p…

GLTF在线场景编辑工具

推荐&#xff1a;使用 NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 以下是Babylon.js Sandbox的主要功能和特点&#xff1a; 1、创建和编辑场景&#xff1a;Babylon.js Sandbox允许用户在一个交互式的3D环境中创建和编辑glTF场景。您可以添加不同类型的物体、调整其位置…

重型并串式液压机械臂建模与simscape仿真

一、建模 Hydraulic manipulator Figure 1 shows different constituting parts of the manipulator considered, with every part labeled using numbers from 1 to 10. For each part, a CAD model is provided. Each file is named in accordance with the corresponding la…

基于YOLOv7的密集场景行人检测识别分析系统

密集场景下YOLO系列模型的精度如何&#xff1f;本文的主要目的就是想要基于密集场景基于YOLOv7模型开发构建人流计数系统&#xff0c;简单看下效果图&#xff1a; 这里实验部分使用到的数据集为VSCrowd数据集。 实例数据如下所示&#xff1a; 下载到本地解压缩后如下所示&…

K8s operator从0到1实战

Operator基础知识 Kubernetes Operator是一种用于管理和扩展Kubernetes应用程序的模式和工具。它们是一种自定义的Kubernetes控制器&#xff0c;可以根据特定的应用程序需求和业务逻辑扩展Kubernetes功能。 Kubernetes Operator基于Kubernetes的控制器模式&#xff0c;通过自…

cocos creator 的input.on 不生效

序&#xff1a; 1、执行input.on的时候发现不生效 2、一直按控制台也打印不出来console.log 3、先收藏这篇&#xff0c;因为到时候cocos要开发serveApi的时候&#xff0c;你得选一款趁手的后端开发并且&#xff0c;对习惯用ts写脚本的你来说&#xff0c;node是入门最快&#xf…

npm install报错 -> npm ERR! Unexpected token ‘.‘ 报错解决办法。

问题原因&#xff1a; 用nvm1.1.7的版本安装了16.x以上的node, 然后再下载依赖的时候就报错了&#xff1b;总结一下就是nvm版本太低了&#xff0c;他的里面没有集成高版本node导致的。 解决办法&#xff1a; 把nvm切换到新版本就行了。 1. 卸载掉当前所有的node nvm unins…

今天开始学习如何正式调查

本节要讲解三个内容 样本容量 调查方式 调查问卷的回收 在正式调查之前需要确定样本容量 就说要准备调查多少人确定好样本容量之后又要考虑设计的调查问卷 是以什么样的方式发出去 问卷的回收又要注意什么问题 要讲的主要内容 先看样本容量 样本容量确定的基本原…

【Paper Reading】CenterNet:Keypoint Triplets for Object Detection

背景 首先是借鉴Corner Net 表述了一下基于Anchor方法的不足&#xff1a; anchor的大小/比例需要人工来确认anchor并没有完全和gt的bbox对齐&#xff0c;不利于分类任务。 但是CornerNet也有自己的缺点 CornerNet 只预测了top-left和bottom-right 两个点&#xff0c;并没有…

S系列数字源表为何如此受欢迎?

为什么选择S系列数字源表? 性能强大-作为电压源和或电流源&#xff0c;并同步测量电流和或电压&#xff0c;支持四象限工作。可以限定电压或电流输出大小&#xff0c;预防器件损坏。覆盖3pA-3A的电流范围100μV-300V的电压范围&#xff0c;全量程测量精度0.03%。 灵活多样-支…

【高频面试题】微服务篇

文章目录 Spring Cloud1.Spring Cloud 5大组件有哪些&#xff1f;2.服务注册和发现是什么意思&#xff1f;Spring Cloud 如何实现服务注册发现&#xff1f;3.负载均衡如何实现的 ?4.什么是服务雪崩&#xff0c;怎么解决这个问题&#xff1f;5.微服务是怎么监控的 业务相关6.项…