线程池的创建方法 总共有 7 种,但总体来说可分为 2 类:
  • 一类是通过 ThreadPoolExecutor 创建的线程池;
  • 另一个类是通过 Executors 创建的线程池。
1. Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待;
2. Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,当执行第二个任务时第一个任务已经完成,
    会复用执行第一个任务的线程,若线程数不够,则一直新建线程;
3. Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执行顺序;
4. Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池;
5. Executors.newSingleThreadScheduledExecutor:创建一个单线程的可以执行延迟任务的线程池;
6. Executors.newWorkStealingPool:创建一个抢占式执行的线程池(任务执行顺序不确定),创建一个具有并行级别的work-stealing线程池,
  【JDK 1.8 添加】可以传入线程的数量,不传入,则默认使用当前计算机中可用的cpu数量,能够合理的使用CPU进行对任务操作(并行操作),适合使用在很耗时的任务中。
7. ThreadPoolExecutor:最原始的创建线程池的方式,它包含了 7 个参数可供设置,后面会详细讲。
例如:
   ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 50, 100, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000));
最大线程数:50: 排队队列最大数:1000
当线程池中正在使用的线程数达到了设置的最大的值(50),而且队列已(1000),还有数据进来的话就会报错。
即: 最大排队数 LinkedBlockingQueue要给一个总得要处理的预估数,比如处理100w的数据。
 
【推荐】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。
3)也就是说如果执行的job很慢,就尽量不要使用上述2种线程池。相反的,如果处理很快的job,则可以使用。
 
参数 1:corePoolSize
核心线程数,线程池中始终存活的线程数。
参数 2:maximumPoolSize
最大线程数,线程池中允许的最大线程数,当线程池的任务队列满了之后可以创建的最大线程数。
参数 3:keepAliveTime
最大线程数可以存活的时间,当线程中没有任务执行时,最大线程就会销毁一部分,最终保持核心线程数量的线程。
参数 4:unit:
单位是和参数 3 存活时间配合使用的,合在一起用于设定线程的存活时间
参数 5:workQueue
一个阻塞队列,用来存储线程池等待执行的任务,均为线程安全,它包含以下 7 种类型:
  • ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
  • LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
  • SynchronousQueue:一个不存储元素的阻塞队列,即直接提交给线程不保持它们。
  • PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
  • DelayQueue:一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素。
  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。与SynchronousQueue类似,还含有非阻塞方法。
  • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
较常用的是 LinkedBlockingQueue 和 Synchronous,线程池的排队策略使用场景:
ArrayBlockingQueue预先分配好一段连续内存,更稳定
LinkedBlockingQueue 读写锁分离,吞吐量更大
参数 6:ThreadFactory
线程工厂,主要用来创建线程,默认为正常优先级、非守护线程。
参数 7:RejectedExecutionHandler
拒绝策略,拒绝处理任务时的策略,系统提供了 4 种可选:
  • AbortPolicy:拒绝并抛出异常。
  • CallerRunsPolicy:使用当前调用的线程来执行此任务。
  • DiscardOldestPolicy:抛弃队列头部(最旧)的一个任务,并执行当前任务。
  • DiscardPolicy:忽略并抛弃当前任务。
默认策略为 AbortPolicy
/**
* @Author Tim
* @Date 2022/6/15 16:03
*/
@Service
public class MultiThreadServiceImpl {
@Autowired
private UserInfoMapper userInfoMapper; /**
* 1.处理速度一般,并且是从回收的线程池中拿出原来的线程复用的.
* 如果执行的job很慢,就尽量不要使用这种线程池。相反的,如果job处理很快,则可以使用。
*/
private static final ExecutorService executorService = Executors.newCachedThreadPool(new BasicThreadFactory.Builder()
.namingPattern("create-card-thread-%d").build()); /**
* 2.处理速度较快,创建一个具有并行级别的work-stealing线程池。 parallelism: 并发级别,适合使用在很耗时的任务中
*/
private static final ExecutorService newWorkStealingPool = Executors.newWorkStealingPool(); /**
* 3.处理速度较快,核心线程数:10, 最大活跃数:50, 最大线程数可以存活的时间:60s, 用来存储线程池等待执行的任务数:100w
* 在不配置RejectedExecutionHandler的情况下,如果实际处理数100w超过了设置队列等待数Queue,会抛异常。
*/
private static final ThreadPoolExecutor threadPoolLocal =
new ThreadPoolExecutor(10, 20, 20, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(1000000)); /**
* 3. 参数不同。
* 配置RejectedExecutionHandler的情况下,不会报错,CallerRunsPolicy:使用当前调用的线程来执行此任务。
*/
private ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 20, TimeUnit.SECONDS,
new ArrayBlockingQueue(20, true), new ThreadPoolExecutor.CallerRunsPolicy()); public void insertUsersByThreads() {
for (int i = 0; i < 1000000; i++) {
//第二种
// CompletableFuture.runAsync(() -> {
// UserInfoPO userInfoPO = new UserInfoPO();
// userInfoPO.setUserEmail("testEmail");
// userInfoPO.setUserName(RandomStringUtils.randomNumeric(4));
// userInfoPO.setUserId(RandomStringUtils.randomNumeric(4));
// userInfoPO.setUserSex("boy");
// System.out.println("userInfoPO....." + userInfoPO.toString());
// userInfoMapper.insert(userInfoPO);
// }, newWorkStealingPool);
//第三种
newWorkStealingPool.execute(() ->{
UserInfoPO userInfoPO = new UserInfoPO();
userInfoPO.setUserEmail("testEmail");
userInfoPO.setUserId(RandomStringUtils.randomNumeric(8));
userInfoPO.setUserName(RandomStringUtils.randomNumeric(8));
userInfoPO.setUserSex("boy");
System.out.println("userInfoPO....." + userInfoPO.toString());
userInfoMapper.insert(userInfoPO);
});
//第一种
// CompletableFuture.runAsync(() -> {
// UserInfoPO userInfoPO = new UserInfoPO();
// userInfoPO.setUserEmail("testEmail");
// userInfoPO.setUserName(RandomStringUtils.randomNumeric(4));
// userInfoPO.setUserId(RandomStringUtils.randomNumeric(4));
// userInfoPO.setUserSex("boy");
// System.out.println("userInfoPO....." + userInfoPO.toString());
// userInfoMapper.insert(userInfoPO);
// }, executorService); }
}

springboot线程池的使用方式1的更多相关文章

  1. [开源项目]可观测、易使用的SpringBoot线程池

    在开发spring boot应用服务的时候,难免会使用到异步任务及线程池.spring boot的线程池是可以自定义的,所以我们经常会在项目里面看到类似于下面这样的代码 @Bean public Ex ...

  2. SpringBoot线程池和Java线程池的实现原理

    使用默认的线程池 方式一:通过@Async注解调用 public class AsyncTest { @Async public void async(String name) throws Inte ...

  3. springboot 线程池

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

  4. springboot线程池的使用和扩展(转)

    springboot线程池的使用和扩展 我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行, ...

  5. springboot线程池的使用和扩展

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

  6. springboot线程池@Async的使用和扩展

    我们常用ThreadPoolExecutor提供的线程池服务,springboot框架提供了@Async注解,帮助我们更方便的将业务逻辑提交到线程池中异步执行,今天我们就来实战体验这个线程池服务: 本 ...

  7. 【Java分享客栈】SpringBoot线程池参数搜一堆资料还是不会配,我花一天测试换你此生明白。

    一.前言   首先说一句,如果比较忙顺路点进来的,可以先收藏,有时间或用到了再看也行:   我相信很多人会有一个困惑,这个困惑和我之前一样,就是线程池这个玩意儿,感觉很高大上,用起来很fashion, ...

  8. SpringBoot线程池的创建、@Async配置步骤及注意事项

    最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信.考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了. 但是 ...

  9. springboot线程池任务调度类 -- ThreadPoolTaskScheduler介绍

    springboot中有一个bean,ThreadPoolTaskScheduler,可以很方便的对重复执行的任务进行调度管理:相比于通过java自带的周期性任务线程池ScheduleThreadPo ...

  10. Springboot 线程池配置

    最近的项目里要手动维护线程池,然后看到一起开发的小伙伴直接用Java了,我坚信Springboot不可能没这功能,于是查了些资料,果然有,这里给一下. 首先我们都知道@Async标签能让方法异步执行, ...

随机推荐

  1. ERP到底是什么?

    ERP,全称企业资源计划,ERP系统主要是优化企业内部的业务流程,用信息化管控的方式进行一系列板块的管理,它可以看作是进销存系统的进阶版,主要针对供应链中下游. ERP的业务覆盖范围广,实际上它更加侧 ...

  2. Codeforces Round 878 (Div. 3)

    Codeforces Round 878 (Div. 3) A:ABC A. Cipher Shifer 题意:在自身后面添加一个字母,但是不能添加自身 思路:找到第二个与自身相符的就再找 #incl ...

  3. 我的PyCharm为什么在linux下打不开?

    PyCharm打不开解决方案 本文基于Xrdp远程连接桌面环境,Unbutu Linux OS,解决办法仅供参考.应以实际情况为准. 问题产生的原因,Xrdp下GUI绘制依赖于Xrdp的渲染,当Xrd ...

  4. Hnswlib 介绍与入门使用

    Hnswlib是一个强大的近邻搜索(ANN)库, 官方介绍 Header-only C++ HNSW implementation with python bindings, insertions a ...

  5. Curator

  6. springboot——yaml格式

  7. Helm Chart 部署 Redis 的完美指南

    目录 一.Helm介绍 二.安装Helm 三.配置Helm的repository 四.部署chart(以部署redis为例) 1. 搜索chart 2. 拉取chart 3. 修改values.yam ...

  8. 文心一言 VS 讯飞星火 VS chatgpt (162)-- 算法导论13.1 2题

    二.用go语言,对图13-1中的红黑树,画出对其调用TREE-INSERT 操作插人关键字 36 后的结果.如果插人的结点被标为红色,所得的树是否还是一棵红黑树?如果该结点被标为黑色呢? 文心一言,代 ...

  9. 【内核】基于 LSM 框架的 ELF 校验控制

    欲实现操作系统对正在加载的 ELF 文件的校验控制,需要借助 LSM 框架. LSM 框架介绍 LSM 全称 Linux Security MOdule,是 Linux 的一个安全模块框架.LSM 为 ...

  10. 支付宝沙箱支付-zfbsxzf

    title: 支付宝沙箱支付 date: 2022-03-03 13:55:15.281 updated: 2022-03-10 16:00:42.331 url: https://www.yby6. ...