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

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

时间:2024-06-21 17:00:01浏览次数:27  
标签:Java 自定义 队列 阻塞 任务 线程 CPU 资源

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

合适的线程数量

对于线程池来说,不同的任务类型可能采取不同的线程数量会取得更好的效果。这是因为有的线程任务对CPU消耗大,任务时间却短,有的任务需要访问网络,需要较长时间才能完成任务。如果只是笼统的定义一个固定大小的线程池,往往会出现CPU不繁忙,但线程池的线程已满,不能再接受任务了,此时却有可能有一些不耗时但耗费CPU的任务没机会执行,从而导致CPU资源浪费等情况。因此,我们需要根据业务特点来定义线程池。

对于CPU 密集型任务,比如加密、解密、压缩、计算等一系列需要大量耗费 CPU 资源的任务。对于这样的任务最佳的线程数为 CPU 核心数的 1~2 倍,如果设置过多的线程数,实际上并不会起到很好的效果。假设设置过多线程,首先会耗费更多资源,大量任务占用线程,但CPU资源有限,这就导致了很多线程上下文切换的成本,此时性能可能不升反降。

对耗时IO任务,比如数据库、文件的读写,网络通信等任务,这种任务的特点是并不会特别消耗 CPU 资源,但是 IO 操作很耗时,总体会占用比较多的时间。这种情况应该设置更多的线程来完成任务,当在等待IO的线程挂起后,此时这些线程并不占用CPU资源,但占用了线程资源,如果没有更多的线程,后续的任务没机会执行,CPU资源也白白浪费。此时如果有更多线程,则这些线程可以去执行其它任务,把CPU资源给利用起来,提高系统的总体性能。

《Java并发编程实战》的作者 Brain Goetz 推荐的计算方法:

线程数 = CPU 核心数 *(1+平均等待时间/平均工作时间)

可见,线程数和平均等待时间成正比,和平均工作时间成反比。总体按这个思路来设置线程池线程大小是可行的,实际还可以根据特定的服务器资源进行压测,根据压测结果来调整以达到更高的性能。

线程池阻塞队列

我们知道使用Executors工具类可以方便的创建线程池(不推荐),其内部实际就是使用ThreadPoolExecutor进行创建,只是提供了一些默认参数,不需要开发者去关注而已。这里不展开Executors给我们提供的那几种线程池,这里关注一下这些线程池里面的阻塞队列类型,为我们自定义线程池作参考。

FixedThreadPool
LinkedBlockingQueue
SingleThreadExecutor
LinkedBlockingQueue
CachedThreadPool
SynchronousQueue
SingleThreadScheduledExecutor
DelayedWorkQueue
ScheduledThreadPoolExecutor
DelayedWorkQueue

首先是FixedThreadPool和SingleThreadExecutor,它们用的阻塞队列都是LinkedBlockingQueue,容量是Integer.MAX_VALUE。因为它们的线程数都是固定的,不能创建非核心线程,因此,队列几乎无限大,核心线程都忙的情况只能把任务放队列,这也是固定线程数的关键。

然后是CachedThreadPool,看名字是一个可缓存的线程池。它的阻塞队列使用的是Synch

标签:Java,自定义,队列,阻塞,任务,线程,CPU,资源
From: https://blog.csdn.net/u012882823/article/details/139797437

相关文章

  • Java入门指南:大一新生的编程初体验
    引言作为一名大一新生,踏入编程世界可能会让人感到既兴奋又有些忐忑。Java作为一种广泛使用的编程语言,以其强大的功能和跨平台的特性,成为了许多计算机科学课程的首选。本文将带你一起走进Java的世界,分享一些入门的知识和学习经验,希望对刚开始学习Java的你有所帮助。1.为什么......
  • 一文读懂Java线程安全
    什么是线程安全性《JavaConcurrencyInPractice》对线程安全的定义如下:当多个线程访问一个类时,如果不用考虑这些线程在运行时环境下的调度和交替执行,并且不需要额外的同步及在调用方代码不作其他的协调,这个类的行为仍是正确的,那么称这个类是线程安全的。简单理解就是,多......
  • 一文读懂Java多线程并发之内存模型
     什么是内存模型?Java内存模型(JavaMemoryModel)描述了Java编程语言中的线程如何与内存进行交互,是和多线程相关的一组规范,需要各个JVM的实现来遵守JMM规范,以便于开发者可以利用这些规范,更方便地开发多线程程序。有了这些规范,即便同一个程序在不同操作系统的虚拟机上运行......
  • 等待执行完后一起收集的多线程
    多线程执行importorg.springframework.scheduling.annotation.Async;importorg.springframework.stereotype.Service;importjava.util.ArrayList;importjava.util.List;importjava.util.concurrent.CompletableFuture;importjava.util.concurrent.ExecutionExceptio......
  • JavaScript状态数据
    最近需要做一个三维场景切换的功能,切换场景后,还可以进行二三维模式的切换,二三维切换时,要定位到当前场景视角,那么场景的视角参数信息就需要保存到状态数据中,以供二三维场景切换时使用。项目是用vue做的,这里并没有使用vue的状态管理库,我是这样实现的:定义状态数据sceneInfolets......
  • 我一直看不明白:“C++会被java/python等这些语言替代”
    在开始前刚好我有一些资料,是我根据网友给的问题精心整理了一份「C++的资料从专业入门到高级教程」,点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!!有些程序,是既可以用c++编写,也可以用java/python编写。如果这类程序以前主要是由c++编写,后来逐渐变成主要......
  • JavaScript的学习之旅之基本数据类型
    一、字面量(常量)和变量字面量:不可变的数据,一般位于等式的右边变量:可变的数据,位于等式的左边<script> //声明一个变量 //用关键字var声明 vara; //要为变量赋值 a=456 a=678 //声明和赋值可以同时进行 varb=34; console.log(b);</script>二、标识符......
  • sqlalchemy根据字典kv自定义表结构
    根据数据的内容自动创建数据库表结构fromsqlalchemyimportcreate_engine,Column,Integer,String,Float,Booleanfromsqlalchemy.ext.declarativeimportdeclarative_basefromsqlalchemy.ormimportsessionmaker,Mapped,mapped_columnBase=declarative_base()......
  • JAVA SSE 服务端单向消息通知
    工作记录关于只需要服务端向web端单向通知的技术SSE的技术落地总结最近有个需求是关于消息的单向通知,原本考虑用websocket,但是技术经理认为太重,建议采用SSE.查阅相关技术后结合实际业务需要新建了一个工具类@Component@Slf4jpublicclassSSEUtils{privatefinalMap<......
  • 一个练习项目,好玩的bbs-java
    java这个我是用springboot做的目录结构   application.ymlspring:datasource:driver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://127.0.0.1:3306/my_bbs?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2b8&am......