一文读懂 Java-线程池

一文读懂Java线程池,强力推荐 线程池是一种线程使用模式。线程池维护多个线程,等待着监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程的开销,另一方面避免了线程数量膨胀导致的过分调度问题。重用已创建的线程:避免因为线程创建和销毁所带来的性能开销控制并发的线程数量:防止因为创建大量线程而导致系统资源耗尽管理线程的生命周期:可以对线程进行统一的分配、调优和监控。 阅读详情

Java-线程池

概念

  • 创建线程要花费昂贵的资源和时间,如果任务来了才创建那么响应时间就会变成,而且一个进程创建的线程数有限
  • 线程池就是首先创建一些线程,它们的集合成为线程池,线程池在系统启动时即创建大量空闲线程,程序将一个任务传给线程池,线程池就会启动一条线程执行这个任务,执行结束后,线程并不会死亡,而是再次返回线程池中成为空闲状态

优势

  • 降低资源消耗,通过重复利用已创建的线程降低创建和销毁的花费
  • 提高响应速度,任务可以不需要等到线程创建就能立即执行
  • 提高线程可管理性,使用线程池可以统一分配,调优和监控

创建

new ThreadPoolExecutor(corePoolSize,maximumPoolSize,keepAliveTime,milliseconds,runnableTaskQueue,handler);
  • corePoolSize: 线程池基本大小,当向线程池提交一个任务时,若线程池已创建的线程数小于corePoolSize,即便此时存在空闲线程,也会通过创建一个新线程来执行该任务,直到已创建的线程数大于或等于corePoolSize时,(除了利用提交新任务来创建和启动线程(按需构造),也可以通过 prestartCoreThread() 或 prestartAllCoreThreads() 方法来提前启动线程池中的基本线程。)
  • maximumPoolSize: 线程池所允许的最大线程个数。当队列满了,且已创建的线程数小于maximumPoolSize,则线程池会创建新的线程来执行任务。对于无界队列,可忽略该参数。
  • keepAliveTime: 线程存活时间,当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。
  • runnableTaskQueue: 任务队列,用于传输和保存等待执行任务的阻塞队列
    • ArrayBlockingQueue: 基于数组结构的有界阻塞队列,FIFO先进先出排序
    • LinkedBlockingQueue: 基于链表结构的阻塞队列,FIFO排序,吞吐量高于ArrayBlockingQueue,静态工厂方法
    • SynchronousQueue: 不存储元素的阻塞队列,每个插入必须等到另一个进程调用移除操作,否则插入一直处于阻塞状态; 吞吐量高于LinkedBlockingQueue
    • PriorityBlockingQueue: 具有优先级的无界阻塞队列
  • threadFactory: 线程工厂,用于创建新线程,threadFactory创建的线程也是采用new Thread()方式,threadFactory创建的线程名都具有统一的风格:pool-m-thread-n(m为线程池的编号,n为线程池内的线程编号)。
  • handler: 线程饱和策略,当任务太多来不及处理时,用于拒绝任务,实现了RejectedExecutionHandler接口
    • AbortPolicy: 直接抛出异常,阻止系统正常运行
    • CallerRunsPolicy: 直接在调用者线程中,运行当前被丢弃的任务
    • DiscardOlderPolicy: 丢弃最老的一个请求,并执行当前任务
    • DiscardPolicy: 丢弃无法处理的任务,不予任何处理

流程

avator

  • 首先判断基本线程池是否已满,未满则创建一个工作线程执行任务,满了则下一步
  • 线程池判断工作队列是否已满,未满则将新提交的任务存储到工作队列中,满了则下一步
  • 线程池判断整个线程池是否已满,未满则创建新的工作线程执行任务,满了则交给饱和策略处理

线程池提交

  • 使用execute提交,没有返回值
  • 使用submit提交,会返回一个future,通过future.get()获取,阻塞直到任务执行完,而get(long timeout,TimeUnit,unit)方法则会阻塞一段时间后立即返回
Future<Object> future = executor.submit(harReturnValuetask);
try{
    Object s = future.get();
}catch (InterruptedException e){
    //处理中断异常
}catch (ExecutionException e){
    //处理无法执行任务异常
}finally{
    //关闭线程池
    executo.shutdown();
}

线程池的关闭

  • 调用线程shutdown或shutdownNow方法,遍历线程池中的的工作线程,然后逐个调用线程的interrupt方法来中断线程,所以无法响应中断的任务可能永远无法终止
  • 区别在于: shutdownNow将线程池的状态设为STOP,然后尝试停止所有的正在执行或暂定任务的线程,并返回等待执行任务的列表; 而shutdown是将线程池的状态设为SHUTDOWN状态,然后中断所有没有正在执行任务的线程
  • 只要调用了两个方法中的任意一个,isShutdown方法就会返回true,而所有的任务都已关闭即所有的线程池关闭,isTerminated才会返回true

线程池的配置

  • 任务性质
    • CPU密集型任务: 尽量使用较小的线程池,核心数+1,若开过多的线程池,会造成CPU过度切换
    • IO密集型任务: 使用稍大的线程池,核心数*2,IO密集型CPU使用率不高,因此CPU在等待IO时有其它线程处理其它任务
    • 混合型任务: 可以将任务分成IO密集型和CPU密集型任务,然后分别用不同的线程池去处理
  • 任务优先级: 高,中,低
  • 任务执行时间: 长,中,短
  • 任务依赖性: 是否依赖其他系统资源,如数据库连接

Java提供的线程池

  • newCachedThreadPool:用来创建一个可以无限扩大的线程池,适用于负载较轻的场景,执行短期异步任务。(可以使得任务快速得到执行,因为任务时间执行短,可以很快结束,也不会造成cpu过度切换)
  • newFixedThreadPool:创建一个固定大小的线程池,因为采用无界的阻塞队列,所以实际线程数量永远不会变化,适用于负载较重的场景,对当前线程数量进行限制。(保证线程数可控,不会造成线程过多,导致系统负载更为严重)
  • newSingleThreadExecutor:创建一个单线程的线程池,适用于需要保证顺序执行各个任务
  • newScheduledThreadPool:适用于执行延时或者周期性任务

线程池的监控

  • taskCount: 线程池需要执行的任务数量
  • completedTaskCount: 已完成的任务数量,小于等于taskCount
  • largestPoolSize: 曾经创建过的最大线程数量,可以判断线程池是否满过
  • getPoolSize: 线程池线程数量,若线程池不销毁的话,线程不会自动销毁
  • getActiveCount: 获取活动的线程数
Java ThreadPoolExecutor 线程池的使用介绍 Executors 是一个Java中的工具类. 提供工厂方法来创建不同类型的线程池,这篇文章主要介绍了Java ThreadPoolExecutor 线程池的使用介绍,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 立即下载

相关推荐

别再只测电压了!用STM32G474的ADC玩点花的:过采样提升精度与多通道扫描实战

本文深入探讨了STM32G474系列单片机的ADC高级应用,包括硬件过采样技术实现16位精度和多通道扫描结合DMA的自动数据采集方案。通过详细的配置步骤和实战案例,帮助开发者突破传统电压测量局限,提升信号采集精度和系统效率,适用于工业监控、医疗设备等高精度应用场景。

weixin_42647395的博客 238

Netty——tackQueue任务队列、线程池异步处理业务

反例示范 在处理复杂繁重的业务的时候,可能会造成Netty中请求的挤压,如下就是业务代码没有异步执行的典型例子 服务端Handler: package com.leolee.netty.test.taskQueue; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import java.util.UUID; /** * @ClassName

保暖透气大裤衩LeoLee的博客 896

【多模态融合】TransFusion学习笔记(1)

工作上主要还是以纯lidar的算法开发,部署以及系统架构设计为主。对于多模态融合(这里主要是只指Lidar和Camer的融合)这方面研究甚少。最近借助和朋友们讨论论文的契机接触了一下这方面的知识,起步是晚了一点,但好歹是开了个头。下面就借助TransFusion论文及其开源代码来串一串这方面的知识。这个很好理解,参考FPointNet网络图示。就是利用现有的2D检测器在图像上提取2D初始框,根据Camera成像原理,捕获2D框视锥内的点云,再利用点云分类模型(如:PointNet)做进一步分类。

4961

线程池实战解析+完整代码

线程池的ThreadPoolConfigProperties文件,来和properties文件里属性进行绑定,实现可配置。 package com.atguigu.gulimall.cart.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /**

是我的温柔啊 753

Android T GPS 定位流程

Gps 定位

好记性不如烂笔头 1355

python多线程实现http代理

python多线程实现http代理文章要求1.py socket模块2.py threading模块3.环境搭建3.1设置代理3.2搭建http简单服务器代码分析1.完整代码2.逻辑结构 文章要求 1.py socket模块 socket模块接触后很简单,我实现的是阻塞性的套接字。 需要了解到,连接套接字,监听套接字,和套接字accept()方法的返回值是元组 数据传递过程sock.recv(1024),sock.send()也不需要转换编码,直接以b"二进制流"传输 2.py threading模块 th

qq_43402663的博客 2508

JUC学习笔记四:ThreadPool线程池

一、ThreadPool线程池 线程池的优势: 在多核cpu没有普及的年代,单核cpu就像是假的多线程。一个cpu需要在多个线程之间来回切换。现在的多核电脑,多个线程可以各自跑在独立的CPU上,不用切换,效率高。 线程池做的工作只要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果线程数量超过了最大数量,超出数量的线程排队等候,等其他线程执行完毕,再从队列中取出任务...

qq_31314141的博客 292

车道线检测(传统基于Opencv的方法)

传统车道线检测方法主要是使用颜色选择、高斯平滑、边缘检测、ROI区域选择、霍夫变换、标定车道边界等Opnecv图像处理操作去检测道路上的车道线,我自己对很多用这类处理对很多道路场景车道线进行过实验,这类算法往往需要人工根据不同街道场景手动去反复调整各算法参数,从而才能使检测效果最佳。

Yangxiaoaijiejie的博客 2072

8 个线程池最佳实践和坑!使用不当直接生产事故!

拓展一下(参见:issue#1737[2]): 线程数更严谨的计算的方法应该是:最佳线程数 = N(CPU 核心数)∗(1+WT(线程等待时间)/ST(线程计算时间)),其中 WT(线程等待时间)=线程运行总时间 - ST(线程计算时间)。

代码界的扛把子 205

图学习——04.HAN(异构图注意力网络)

什么是异构图,什么是元路径,什么是HAN,怎么计算attention,节点级别的attention和语义级别的attention

m0_51474171的博客 2999

YOLO11改进策略【独家融合改进】| RCSOSA + SPD + WFU

SPD-Conv是一种新的 CNN 构建模块,用于替代传统 CNN 架构中使用的步长卷积(strided convolution)和池化(pooling)层,它由空间到深度(Space-to-depth,SPD)层和非步长卷积(non - strided convolution)层组成。WFU模块通过小波变换的频率分解与跨尺度融合机制,解决了传统上采样过程中的混叠和细节丢失问题,实现了高效、高保真的面部细节重建。

Limiiiing的博客 449

如何优雅的自定义 ThreadPoolExecutor 线程池

java 中经常需要用到多线程来处理一些业务,非常不建议单纯使用继承Thread或者实现Runnable接口的方式来创建线程,那样势必有创建及销毁线程耗费资源、线程上下文切换问题。同时创建过多的线程也可能引发资源耗尽的风险,这个时候引入线程池比较合理,方便线程任务的管理。

qq_43842093的博客 1597

【Bug已解决】Codex App returns 401 Missing bearer/basic authentication after login on multiple Windows la

原始报错:Codex App returns 401 Missing bearer/basic authentication after login on multiple Windows laptops场景:用户在 Windows 笔记本上登录应用成功了,但随后每个业务请求都返回 401,提示"Missing bearer/basic authentication"。登录态像是"假的"——明明登了,请求却没带任何认证信息。多台 Windows 设备都能复现。

一键难忘的博客 593

一文读懂java线程池

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。线程对象在不同的时期有不同的状态。那么Java中的线程存在哪几种状态呢?Java中的线程/* 新建 */NEW ,/* 可运行状态 */RUNNABLE ,/* 阻塞状态 */BLOCKED ,/* 无限等待状态 */WAITING ,/* 计时等待 *//* 终止 */TERMINATED;// 获取当前线程的状态通过源码我们可以看到Java中的线程存在6种状态,每种线程状态的含义如下。

m0_58975186的博客 781

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

一文读懂 Java 线程池

在生产环境,我们经常面临的情况是:处理某次请求的时间非常短暂,但是请求量很大。在这种情况下,如果为每个请求单独创建一个线程,有限的硬件资源有可能会被OS创建线程,切换线程状态、销毁线程这些操作所占用,用于业务处理的资源反而减少了。所以理想的处理方式是:将请求的线程数量控制在一个范围内,既保证后续的请求不会等待太长时间,又保证物理机将足够的资源用于请求处理本身。开发者通常利用 ThreadPoolExecutor 类的构造函数来创建不同配置的线程池: 透过这个构造方法,可以大致勾勒出线程池的基本组

weixin_70730532的博客 318

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

一文读懂Java线程池

文章目录1 线程池前置知识1.1 Callable1.2 Future1.3 FutureTask2 ThreadPoolExecutor2.1 ThreadPoolExecutor继承体系2.2 ThreadPoolExecutor参数2.3 ThreadPoolExecutor任务提交流程2.4 线程工厂2.5 拒绝策略2.6 Executors提供的线程池2.6.1 newCachedThreadPool2.6.2 newFixedThreadPool2.6.3 newSingleThreadExec

一切皆有可能! 264

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

一文读懂Java线程池之线程复用原理

在Java中,我们正常创建线程执行任务,一般都是一条线程绑定一个Runnable执行任务。而Runnable实际只是一个普通接口,真正要执行,则还是利用了Thread类的run方法。这个rurn方法由native本地方法start0进行调用。我们看Thread类的run方法实现/*** */@Overrideif (target!= null) {很明显,Thread类的run方法就是使用构造Thread类传入来的Runnable对象,执行Runnable的run方法。

ningkangming的博客 2014

一文读懂Java线程池ThreadPoolExecutor的使用

再实际项目中,我们可能会处理执行时间非常短但是数量非常大的请求,这个时候如果为每一个请求创建一个新的线程,可能会导致性能瓶颈。因为线程的创建和销毁的时间可能会大于任务执行的时间,系统性能就会大幅度降低。 JDK1.5提供了线程池的支持,它通过线程的复用技术从而省去线程的频繁创建来达到处理大量并发请求的目的。线程池的原理就是创建了一个运行效率比较优异的“ThreadPool”再池中对线程对象进行创建销毁的管理,使用池时只需要执行具体的任务即可,线程对象的处理再池中被封装了。如下是线程池的一个简单的例子:

微服务技术栈 852

一文读懂Java线程池之线程池优点、使用方法、参数含义及线程池运转机制

如果满了,则把任务放到阻塞队列中,等待有空闲的核心线程来执行任务。注意到构建线程池的参数中有keepAliveTime+时间单位这两个参数,这两个参数正是用于回收非核心线程用的,当非核心线程没任务了,空闲时间达到keepAliveTime配置的值后将会被线程池销毁以回收一些系统资源。线程池就是为了解决上述问题出现的,解决问题的思路很清晰,就是创建好一定数量的线程,有任务来了就用这些线程来执行任务,任务过多把池里面的线程都占用了就放队列排队等候其他任务执行,一旦有空闲线程就可以从队列里面取出任务并执行。

ningkangming的博客 1346

一文读懂线程池的实现原理,java面试写代码

上个月底群里的一个好朋友向老周提出啥时候分享 ThreadPoolExecutor 解析大全,我说后面会提上日程;然后前些天有读者也反馈说在面试中有被问到线程池,问我啥时候出一篇线程池相关的文章。今天老周就来安排一波线程池,现在很多公司都喜欢问线程池相关的面试题,为什么面试官这么热衷于问线程池相关的面试题呢?因为这是多线程的基础,ThreadPoolExecutor 的几个重要参数你必须会知道设置以及什么场景选择哪种 Executor 、线程池队列的选择以及相应的拒绝策略。

2401_83621499的博客 562

auto.js停止所有线程_一文读懂 Java 线程池

为什么要用线程池在生产环境,我们经常面临的情况是: 处理某次请求的时间非常短暂,但是请求量很大。在这种情况下,如果为每个请求单独创建一个线程,有限的硬件资源有可能会被OS创建线程,切换线程状态、销毁线程这些操作所占用,用于业务处理的资源反而减少了。所以理想的处理方式是: 将请求的线程数量控制在一个范围内,既保证后续的请求不会等待太长时间,又保证物理机将足够的资源用于请求处理本身。线程池设计与结构开...

weixin_39548968的博客 300

一文读懂Java线程池之自定义线程池、设置合适的线程数量、线程池阻塞队列、线程拒绝策略

在上篇我们学习了线程池各个参数的含义,线程池任务处理流程,使用线程池的好处等内容,本篇我们学习如何创建一个适合我们业务的线程池。为此,我们有必要先学习一下如何大概确定我们线程池核心线程数、怎么设置阻塞队列的类型与大小、当线程池没有能力处理任务了该如何使用拒绝策略等内容。

ningkangming的博客 2696

一文读懂Java线程池ScheduledThreadPoolExecutor的使用与运行机制

ScheduledThreadPoolExecutor继承自ThreadPoolExecutor。它主要用来在给定的延迟之后运 行任务,或者定期执行任务。ScheduledThreadPoolExecutor的功能与Timer类似,但 ScheduledThreadPoolExecutor功能更强大、更灵活。Timer对应的是单个后台线程,而 ScheduledThreadPoolExecutor可以在构造函数中指定多个对应的后台线程数。 和ThreadPoolExecutor类似,ScheduledTh

微服务技术栈 3489

一文读懂 Java 线程池拒绝策略:从原理到实践(含 CallerRunsPolicy 等 4 种策略全解析)

在 Java 并发编程中,线程池是控制线程数量、提升资源利用率的核心组件。但当线程池的任务队列满了、且已达到最大线程数时,新提交的任务会被拒绝 —— 这时候就需要拒绝策略来决定如何处理这些被拒绝的任务。         今天我们就来详细拆解 Java 线程池的 4 种内置拒绝策略,包括大家常问的CallerRunsPolicy,以及默认的AbortPolicy、“静默丢弃” 的DiscardPolicy、“丢弃 oldest” 的DiscardOldestPolicy,帮你搞懂每种策略的适用场景和实践用法

lijingxiaov5的博客 1696

2024最新Java算法相关面试大,一文读懂线程池的实现原理(1),2024最新Java大厂面试题来袭

这里你有可能问了,老周啊,CAPACITY = (1

2401_84103100的博客 973

《别再懵圈!一文读懂线程池源码逻辑》

首先从上帝视角全局梳理,接着分析需要理解的点,最后以及需要掌握的点,总结贯穿其中。相信你们会受益匪浅!

JIGUANGDI 1525
上一篇: 操作系统-进程
下一篇: 操作系统-线程
广州彭于晏
博客等级 码龄8年 10粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值