java线程池实战

news/2025/2/13 3:42:51/

线程池是一种常用的并发编程技术,它可以有效管理和复用线程,提高程序的性能和资源利用率。线程池本质是池化技术,和连接池类似,创建连接与关闭连接属于耗时操作,创建线程与销毁线程也属于耗时重操作。为了提高效率,先提前创建好一批线程,当有需要使用线程时从线程池取出,用完后放回线程池,这样避免了频繁创建与销毁线程。

线程池参数

核心参数

线程池的核心参数决定了池的类型,进而决定了池的特性。

参数解释工作队列
corePoolSize核心线程数池中长期维护的线程数量,不主动回收
maximumPoolSize最大线程数最大线程数大于等于核心线程数
keepAliveTime线程最大空闲时间非核心线程最大空闲时间,超时回收线程
workQueue工作队列工作队列直接决定线程池的类型

参数与池的关系

Executors类默认创建线程池与参数对应关系。 

线程池corePoolSizemaximumPoolSizekeepAliveTimeworkQueue
newCachedThreadPool0Integer.MAX_VALUE60SynchronousQueue
newSingleThreadExecutor110LinkedBlockingQueue
newFixedThreadPoolNN0LinkedBlockingQueue
newScheduledThreadPoolNInteger.MAX_VALUE0DelayedWorkQueue

线程池类型

根据使用场景选择对应的线程池。

线程池特点适用场景
newCachedThreadPool超时未使用的线程回自动销毁,有新任务时自动创建适用于低频、集中式任务。回收线程的目的是节约线程长时间空闲而占有的资源。
newSingleThreadExecutor线程池中有且只有一个线程异步顺序执行任务
newFixedThreadPool线程池中有固定数量的线程,且一直存在适用于高频的任务,即线程在大多数时间里都处于工作状态。
newScheduledThreadPool定时线程池与定时调度相关联

提交任务方式

往线程池中提交任务,主要有两种方法:提交无返回值的任务和提交有返回值的任务。

  • execute用于提交不需要返回结果的任务。
  • submit用于提交一个需要返回果的任务。该方法返回一个Future对象,通过调用这个对象的get()方法,我们就能获得返回结果。get()方法会一直阻塞,直到返回结果返回。

 在提交任务时,如果无返回值任务,优先使用execute方法。

关闭线程池

在线程池使用完成之后,我们需要对线程池中的资源进行释放操作,这就涉及到关闭功能。

1.关闭线程池的意义 

线程池作为任务的管理者,需要优雅的关闭,原因是如果不手动关闭线程池,线程池中正在执行执行的线程以及队列中还未执行任务将会变得极不可控,如果处理不当,可能造成数据丢失,业务请求结果不正确等问题。

如果业务能够忽略上述影响,那么直接关闭JVM,那么连接池资源会自动释放,不需要手动关闭。

 2.关闭线程池的方式

调用线程池对象的shutdown()shutdownNow()方法来关闭线程池。

  • shutdown()会将线程池状态置为SHUTDOWN,不再接受新的任务,同时会等待线程池中已有的任务执行完成再结束。
  • shutdownNow()会将线程池状态置为SHUTDOWN,对所有线程执行interrupt()操作,清空队列,并将队列中的任务返回回来。

关闭线程池涉及到两个返回boolean的方法,isShutdown()isTerminated,分别表示是否关闭和是否终止。 

工作队列

工作队列是BlockingQueue类型的,理论上只要是它的子类,我们都可以用来作为等待队列。常用的工作队列有四种。

  • ArrayBlockingQueue 队列是有界的,基于数组实现的阻塞队列
  • LinkedBlockingQueue 队列可以有界,也可以无界。基于链表实现的阻塞队列
  • SynchronousQueue 不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作将一直处于阻塞状态。该队列是Executors.newCachedThreadPool()的默认队列
  • PriorityBlockingQueue 带优先级的无界阻塞队列

通常情况下,我们需要指定阻塞队列的上界(比如1024)。如果执行的任务很多,我们可能需要将任务进行分类,然后将不同分类的任务放到不同的线程池中执行。

拒绝策略

所谓拒绝策略,是指当线程池满了、队列也满了的时候,对新提交任务采取的态度。常见如下四种策略:

  • CallerRunsPolicy 在调用者线程执行
  • AbortPolicy 直接抛出RejectedExecutionException异常
  • DiscardPolicy 任务直接丢弃,不做任何处理
  • DiscardOldestPolicy 丢弃队列里最旧的那个任务,再尝试执行当前任务

这四种策略各有优劣,比较常用的是DiscardPolicy。如果需要实现自定义的拒绝策略, 通过实现RejectedExecutionHandler接口的方式来实现。

创建线程池

 /*** 核心线程池数量*/int corePoolSize = 5;/*** 最大线程池的数量 非核心线程池=最大线程池-核心线程池*/int maximumPoolSize = 10;/*** 非核心线程池最大空闲时间*/int keepAliveTime = 1;/*** 非核心线程池最大空闲时间单位*/TimeUnit unit = TimeUnit.MINUTES;/*** 阻塞队列*/BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(10);/*** 线程池工厂*/ThreadFactory threadFactory = Executors.defaultThreadFactory();/*** 异常处理策略(报错)*/RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();/*** 手动构造线程池*/ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);threadPoolExecutor.execute(() ->{System.out.println("开始任务");});

 


http://www.ppmy.cn/news/1157825.html

相关文章

网工配置命令总结(1)---Web访问及vlan配置

目录 1.Telnet远程登录设备 2.用户通过Web网管登录设备 3.端口隔离功能的实现 4.配置vlan聚合 5.部分vlan间互通&#xff0c;部分vlan间隔离&#xff0c;vlan内用户隔离 6.限制内网网段互访 1.Telnet远程登录设备 1.使能服务器功能 <HUAWEI> system-view [HUAWEI] …

SpringBoot入门详解

目录 因何而生的SpringBoot 单体架构的捉襟见肘 SpringBoot的优点 快速入门 高曝光率的Annotation SpringBoot的工作机制 了解SpringBootApplication SpringBootConfiguration EnableAutoConfiguration 自动配置的幕后英雄&#xff1a;SpringFactoriesLoader Compon…

Linux多线程编程- 无名信号量

简介 无名信号量&#xff08;在 POSIX 环境下通常指 sem_t 类型的信号量&#xff09;是用于同步和互斥的原语&#xff0c;它允许线程和进程按照预期的顺序执行&#xff0c;并确保对共享资源的安全访问。无名信号量与命名信号量的主要区别在于它们的可见性和生命周期。无名信号…

新能源电池试验中准确模拟高空环境大气压力的解决方案

摘要&#xff1a;针对目前新能源电池热失控和特性研究以及生产中缺乏变环境压力准确模拟装置、错误控制方法造成环境压力控制极不稳定以及氢燃料电池中氢气所带来的易燃易爆问题&#xff0c;本文提出了相应的解决方案。方案的关键一是采用了低漏率电控针阀作为下游控制调节阀实…

第一章:变量和简单的数据类型

第一节 变量 variable(变量)&#xff0c;每个变量指向一个值————与该变量相关联的信息 message"hello python world!" print(message) 1.1变量的命名和使用 1.变量名只能包含数字(0~9)、字母(Aa~Zz)和下划线(_)。变量可以使用字母和下划线作为开头&#xff0c…

Junit 单元测试之错误和异常处理

错误和异常处理是测试中非常重要的部分。假设我们有一个服务&#xff0c;该服务从数据库中获取用户。现在&#xff0c;我们要考虑的错误场景是&#xff1a;数据库连接断开。 整体代码示例 首先&#xff0c;为了简化&#xff0c;我们让服务层就是简单的类&#xff0c;然后使用I…

字节码进阶之Lombok底层原理

字节码进阶之Lombok底层原理 文章目录 前言lombok 原理Lombok工作原理 举个简单的例子 前言 例如&#xff0c;我们经常在Java代码中为类的属性生成getter和setter方法&#xff0c;这是一种重复且繁琐的工作。使用Lombok可以极大地简化这个过程。 假设我们有如下的Java类&…

LockSupport-park和unpark编码实战

package com.nanjing.gulimall.zhouyimo.test;import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport;/*** author zhou* version 1.0* date 2023/10/16 9:11 下午*/ public class LockSupportDemo {public static void main(String[] args) {…