【多线程】为什么不建议使用Executors来创建线程池?

news/2025/2/28 17:55:14/

目录

        • 一、线程池类型
          • 1.1 固定数量的线程池
          • 1.2 单个线程线程池
          • 1.3 带缓冲的线程池
          • 1.4 延迟任务线程池
        • 二、代码示例
          • 2.1 固定数量的线程池
          • 2.2 单个线程的线程池
          • 2.3 带缓冲的线程池
          • 2.4 延迟线程池

一、线程池类型

1.1 固定数量的线程池
  • 1.创建的队列为LinkedBlockingQueue,是一个无界阻塞队列,可以放任意数量的任务
  • 2.使用固定数量的线程池执行任务,当任务过多会不断添加到任务队列中,任务越多占用的内存就越多,会耗尽内存导致oom
  • 3.核心线程数等于最大线程数,没有救急线程,无需超时时间
  • 4.适用于任务量已知,相对耗时的任务
1.2 单个线程线程池
  • 1.多个任务排队执行
  • 2.线程数固定为1,任务数多于1时,会放入无界队列排队
  • 3.任务执行完毕,唯一的线程也不会释放
  • 4.与自己创建的线程的区别:自己创建一个单线程串行执行任务,任务执行失败而终止则没有任务不就措施,线程池执行失败会新建一个线程,保证线程池的正常工作
  • 5.线程个数始终为1,后续不能修改;固定数量的线程池初始为1,后续还可以修改。单个线程线程池创建时FinalizableDelegatedExecutorService用的是装饰器模式,只对外暴露ExecutorService接口,不能调用ThreadPoolExecutor中特有的方法,固定数量线程池对外暴露的是ThreadPoolExecutor对象,可以强转,调用setCorePoolSize等方法进行修改
1.3 带缓冲的线程池
  • 1.核心线程数是0,最大线程数是Integer.MAX_VALUE,救急线程的空闲生存时间是60s
  • 2.全部是救急线程(60秒后可以回收)
  • 3.可以无限创建救急线程
  • 4.队列采用了同步队列SynchronousQueue [ˈsɪŋkrənəs],没有容量,任务放入队列若是没有线程来取任务,任务是放不进去的
  • 5.整个线程池表现为线程数会根据任务量不断增长,没有上限,当任务执行完毕,空闲1分钟后释放线程
  • 6.适合任务数比较密集,每个任务执行时间较短的情况
1.4 延迟任务线程池
  • 1.可以延迟执行任务
  • 2.DelayedWorkQueue延迟队列
  • 3.无界队列,可能会导致OOM

二、代码示例

2.1 固定数量的线程池
// 创建一个3个线程数量的线程池
ExecutorService executorService = Executors.newFixedThreadPool(3);
// 源码
public static ExecutorService newFixedThreadPool(int nThreads) {return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
2.2 单个线程的线程池
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 源码
public static ExecutorService newSingleThreadExecutor() {return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}
// 单线程池执行失败,会创建新的线程来执行后续的任务
package com.learning.threadpool;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** @Description 单线程的线程池执行失败会创建新线程继续处理后续任务**/
public class SingleThreadPool {public static void main(String[] args) {ExecutorService executorService = Executors.newSingleThreadExecutor();for (int i = 0; i < 3; i++) {int finalI = i;executorService.execute(()->{if(finalI==0){int a = finalI / 0;}System.out.println(finalI);});}}
}
2.3 带缓冲的线程池
ExecutorService executorService = Executors.newCachedThreadPool();
// 源码
public static ExecutorService newCachedThreadPool() {return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}
2.4 延迟线程池
// 源码
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {return new ScheduledThreadPoolExecutor(corePoolSize);
}
package com.learning.threadpool;import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;/*** @Description 延迟线程池**/
public class NewScheduledThreadPool {public static void main(String[] args) {ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);System.out.println("开始");for (int i = 0; i < 10; i++) {int finalI = i;scheduledExecutorService.schedule(()->{System.out.println(finalI);}, 5, TimeUnit.SECONDS);}}
}

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

相关文章

C技能树:判断闰年

输入任意年份的正整数n&#xff0c;判断该年份是否为闰年。请选出错误答案。 闰年的定义&#xff1a;能被400整除的年份为闰年;能被4整除同时不能被100整除年份为闰年。 #include <stdio.h> int main(int argc, char** argv) {int year;printf("请输人年份&#x…

Linux网络基础

这篇博客我们将初步讲解网络中的一些基本概念&#xff0c;为后续套接字编程和的学习和对网络进行一步的了解打下一定基础。 目录 1.网络发展背景 2.IP地址 2.1内容 2.2本质 3.端口 3.1内容 3.2本质 4.协议 4.1内容 4.2分层 5.网络字节序 5.1引入 5.2内容 1.网络…

RabbitMQ--详情概述

一、消息队列(Rabbit Message Queue) 1、概念 消息队列是一种应用之间的通信方式&#xff0c;消息发送之后可以立即返回&#xff0c;由消息系统来确保消息的可靠传递。消息发布者只发布消息到MQ&#xff0c;消息使用者值从MQ中拿消息&#xff0c;两者不知道对方的存在。 简…

Java运行时内存管理

一、前言 希望能在我们平时开发写代码的时候&#xff0c;能够知道当前写的这段代码&#xff0c;内存方面是如何分配的。 我们深知&#xff0c;一个Java程序员在很多时候根本不用操心内存的释放&#xff0c;而是依靠JVM去管理&#xff0c;以前写C代码的时候&#xff0c;却要时刻…

掌握Linux字符设备驱动程序的核心要点

目录标题 Linux设备驱动程序的重要性 | Importance of Linux Device Drivers字符设备驱动程序概述 | Overview of Character Device Drivers Linux字符设备驱动程序的基本组件 | Basic Components of Linux Character Device Drivers文件操作结构体 | File Operations Structur…

Sharding-JDBC之垂直分库水平分表

目录 一、简介二、maven依赖三、数据库3.1、创建数据库3.2、订单表3.3、用户表 四、配置&#xff08;二选一&#xff09;4.1、properties配置4.2、yml配置 五、实现5.1、实体5.2、持久层5.3、服务层5.4、测试类5.4.1、保存订单数据5.4.2、查询订单数据5.4.3、保存用户数据5.4.4…

中国剩余定理在RSA解密中的效率提升逻辑

中国剩余定理&#xff08;Chinese Remainder Theorem&#xff0c;简称CRT&#xff09;是数论中的一项重要定理。它提供了一种方法&#xff0c;可以从一系列模不同整数的同余方程组中&#xff0c;找到一个整数解。CRT在密码学、计算机科学和工程中都有广泛应用。 假设我们有一组…

构建一个pytorch手写网络的基本流程

文章目录 从简单手写数字识别开始基本网络框架的使用使用pytorch构建网络——基本组件定义一个简单的网络使用pytorch加载和处理数据数据流的基本单位&#xff1a;Tensor下载数据集 & 加载 使用pytorch训练及保存模型训练的基本逻辑——梯度下降 & 反向传播训练代码模型…