详解线程池的作用及Java中如何使用线程池

article/2025/9/28 23:05:59


服务端应用程序(如数据库和 Web 服务器)需要处理来自客户端的高并发、耗时较短的请求任务,所以频繁的创建处理这些请求的所需要的线程就是一个非常消耗资源的操作。常规的方法是针对一个新的请求创建一个新线程,虽然这种方法似乎易于实现,但它有重大缺点。为每个请求创建新线程将花费更多的时间,在创建和销毁线程时花费更多的系统资源。因此同时创建太多线程的 JVM 可能会导致系统内存不足,这就需要限制要创建的线程数,也就是需要使用到线程池。

一、什么是 Java 中的线程池?

线程池技术就是线程的重用技术,使用之前创建好的线程来执行当前任务,并提供了针对线程周期开销和资源冲突问题的解决方案。 由于请求到达时线程已经存在,因此消除了线程创建过程导致的延迟,使应用程序得到更快的响应。

  • Java提供了以Executor接口及其子接口ExecutorServiceThreadPoolExecutor为中心的执行器框架。通过使用Executor,完成线程任务只需实现 Runnable接口并将其交给执行器执行即可。
  • 为您封装好线程池,将您的编程任务侧重于具体任务的实现,而不是线程的实现机制。
  • 若要使用线程池,我们首先创建一个 ExecutorService对象,然后向其传递一组任务。ThreadPoolExcutor 类则可以设置线程池初始化和最大的线程容量。

上图表示线程池初始化具有3 个线程,任务队列中有5 个待运行的任务对象。

执行器线程池方法

方法描述
newFixedThreadPool(int)创建具有固定的线程数的线程池,int参数表示线程池内线程的数量
newCachedThreadPool()创建一个可缓存线程池,该线程池可灵活回收空闲线程。若无空闲线程,则新建线程处理任务。
newSingleThreadExecutor()创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务
newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行

在固定线程池的情况下,如果执行器当前运行的所有线程,则挂起的任务将放在队列中,并在线程变为空闲时执行。

二、线程池示例

在下面的内容中,我们将介绍线程池的executor执行器。

创建线程池处理任务要遵循的步骤

  1. 创建一个任务对象(实现Runnable接口),用于执行具体的任务逻辑
  2. 使用Executors创建线程池ExecutorService
  3. 将待执行的任务对象交给ExecutorService进行任务处理
  4. 停掉 Executor 线程池
//第一步: 创建一个任务对象(实现Runnable接口),用于执行具体的任务逻辑 (Step 1) 
class Task implements Runnable  {private String name;public Task(String s) {name = s;}// 打印任务名称并Sleep 1秒// 整个处理流程执行5次public void run() {try{for (int i = 0; i<=5; i++) {if (i==0) {Date d = new Date();SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");System.out.println("任务初始化" + name +" = " + ft.format(d));//第一次执行的时候,打印每一个任务的名称及初始化的时间}else{Date d = new Date();SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");System.out.println("任务正在执行" + name +" = " + ft.format(d));// 打印每一个任务处理的执行时间}Thread.sleep(1000);}System.out.println("任务执行完成" + name);}  catch(InterruptedException e)  {e.printStackTrace();}}
}

测试用例

public class ThreadPoolTest {// 线程池里面最大线程数量static final int MAX_SIZE = 3;public static void main (String[] args) {// 创建5个任务Runnable r1 = new Task("task 1");Runnable r2 = new Task("task 2");Runnable r3 = new Task("task 3");Runnable r4 = new Task("task 4");Runnable r5 = new Task("task 5");// 第二步:创建一个固定线程数量的线程池,线程数为MAX_SIZEExecutorService pool = Executors.newFixedThreadPool(MAX_SIZE);// 第三步:将待执行的任务对象交给ExecutorService进行任务处理pool.execute(r1);pool.execute(r2);pool.execute(r3);pool.execute(r4);pool.execute(r5);// 第四步:关闭线程池pool.shutdown();}
} 

示例执行结果

任务初始化task 1 = 05:25:55
任务初始化task 2 = 05:25:55
任务初始化task 3 = 05:25:55
任务正在执行task 3 = 05:25:56
任务正在执行task 1 = 05:25:56
任务正在执行task 2 = 05:25:56
任务正在执行task 1 = 05:25:57
任务正在执行task 3 = 05:25:57
任务正在执行task 2 = 05:25:57
任务正在执行task 3 = 05:25:58
任务正在执行task 1 = 05:25:58
任务正在执行task 2 = 05:25:58
任务正在执行task 2 = 05:25:59
任务正在执行task 3 = 05:25:59
任务正在执行task 1 = 05:25:59
任务正在执行task 1 = 05:26:00
任务正在执行task 2 = 05:26:00
任务正在执行task 3 = 05:26:00
任务执行完成task 3
任务执行完成task 2
任务执行完成task 1
任务初始化task 5 = 05:26:01
任务初始化task 4 = 05:26:01
任务正在执行task 4 = 05:26:02
任务正在执行task 5 = 05:26:02
任务正在执行task 4 = 05:26:03
任务正在执行task 5 = 05:26:03
任务正在执行task 5 = 05:26:04
任务正在执行task 4 = 05:26:04
任务正在执行task 4 = 05:26:05
任务正在执行task 5 = 05:26:05
任务正在执行task 4 = 05:26:06
任务正在执行task 5 = 05:26:06
任务执行完成task 4
任务执行完成task 5

如程序执行结果中显示的一样,任务 4 或任务 5 仅在池中的线程变为空闲时才执行。在此之前,额外的任务将放在待执行的队列中。

线程池执行前三个任务,线程池内线程回收空出来之后再去处理执行任务 4 和 5

使用这种线程池方法的一个主要优点是,假如您希望一次处理10000个请求,但不希望创建10000个线程,从而避免造成系统资源的过量使用导致的宕机。您可以使用此方法创建一个包含500个线程的线程池,并且可以向该线程池提交500个请求。
ThreadPool此时将创建最多500个线程,一次处理500个请求。在任何一个线程的进程完成之后,ThreadPool将在内部将第501个请求分配给该线程,并将继续对所有剩余的请求执行相同的操作。在系统资源比较紧张的情况下,线程池是保证程序稳定运行的一个有效的解决方案。

三、使用线程池的注意事项与调优

  1. 死锁: 虽然死锁可能发生在任何多线程程序中,但线程池引入了另一个死锁案例,其中所有执行线程都在等待队列中某个阻塞线程的执行结果,导致线程无法继续执行。
  2. 线程泄漏 : 如果线程池中线程在任务完成时未正确返回,将发生线程泄漏问题。例如,某个线程引发异常并且池类没有捕获此异常,则线程将异常退出,从而线程池的大小将减小一个。如果这种情况重复多次,则线程池最终将变为空,没有线程可用于执行其他任务。
  3. 线程频繁轮换: 如果线程池大小非常大,则线程之间进行上下文切换会浪费很多时间。所以在系统资源允许的情况下,也不是线程池越大越好。

线程池大小优化: 线程池的最佳大小取决于可用的处理器数量和待处理任务的性质。对于CPU密集型任务,假设系统有N个逻辑处理核心,N 或 N+1 的最大线程池数量大小将实现最大效率。对于 I/O密集型任务,需要考虑请求的等待时间(W)和服务处理时间(S)的比例,线程池最大大小为 N*(1+ W/S)会实现最高效率。

不要教条的使用上面的总结,需要根据自己的应用任务处理类型进行灵活的设置与调优,其中少不了测试实验。


http://chatgpt.dhexx.cn/article/mEPi4j0c.shtml

相关文章

线程池作用及Executors方法讲解

线程池的作用: 线程池作用就是限制系统中执行线程的数量。 根据系统的环境情况&#xff0c;可以自动或手动设置线程数量&#xff0c;达到运行的最佳效果&#xff1b;少了浪费了系统资源&#xff0c;多了造成系统拥挤效率不高。用线程池控制线程数量&#xff0c;其他线程排…

Qt工作笔记-线程池作用之一:限制系统中执行线程的数量

一、线程池的作用&#xff1a; 线程池作用就是限制系统中执行线程的数量。 根据系统的环境情况&#xff0c;可以自动或手动设置线程数量&#xff0c;达到运行的最佳效果&#xff1b;少了浪费了系统资源&#xff0c;多了造成系统拥挤效率不高。用线程池控制线程数量&#xff0c;…

Android:Android线程和线程池的作用

文章目录 前言一、线程池概念好处线程池的创建参数含义工作机制RejectedExecutionHandler&#xff08;饱和策略&#xff09; 二、Android线程形态1.AsyncTask特点作用缺点生命周期注意事项 具体使用源码分析小结 2.HandlerThread特点作用具体使用 3.IntentService源码分析 总结…

线程池作用和参数原理

线程池的作用 减少资源的开销 减少了每次创建线程、销毁线程的开销。 提高响应速度每次请求到来时&#xff0c;由于线程的创建已经完成&#xff0c;故可以直接执行任务&#xff0c;因此提高了响应速度。提高线程的可管理性 线程是一种稀缺资源&#xff0c;若不加以限制&#x…

线程池作用、用法以及原理

线程池 作用用法建议设定大小快捷构造线程池submit与executeshutdown与shutdownNowFuture与FutureTast代码 状态底层原理继承关系主要参数工作原理饱和策略连接复用 作用 1&#xff0c;降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗 2&#xff0c;提高…

线程池-线程池的好处

1.线程池的好处。 线程使应用能够更加充分合理的协调利用cpu 、内存、网络、i/o等系统资源。 线程的创建需要开辟虚拟机栈&#xff0c;本地方法栈、程序计数器等线程私有的内存空间。 在线程的销毁时需要回收这些系统资源。频繁的创建和销毁线程会浪费大量的系统资源&#xff0…

什么是线程池,线程池的作用

线程池&#xff0c;--其实就是一个 容纳多个线程的容器 &#xff0c;其中的线程可以反复使用&#xff0c;省去了频繁创建线程对象的操作 &#xff0c;--无需反复创建线程而消耗过多资源。 创建销毁线程是一个非常消耗性能的。 我们详细的解释一下为什么要使用线程池&#xff1f…

华为防火墙实战配置教程,太全了

防火墙是位于内部网和外部网之间的屏障&#xff0c;它按照系统管理员预先定义好的规则来控制数据包的进出。防火墙是系统的第一道防线&#xff0c;其作用是防止非法用户的进入。 本期我们一起来总结下防火墙的配置&#xff0c;非常全面&#xff0c;以华为为例。 防火墙的配置…

防火墙配置(命令)

拓扑图&#xff1a; 目的&#xff1a;PC1和PC2相互ping通。 配置命令&#xff1a; FW1: //添加端口IP [SRG-GigabitEthernet0/0/0]interface GigabitEthernet0/0/1 [SRG-GigabitEthernet0/0/1]ip add 192.168.1.1 24 [SRG]inter g0/0/2 [SRG-GigabitEthernet0/0/2]ip add 10.…

防火墙基础配置(二)

拓补图&#xff1a; 方案一&#xff08;子接口的形式&#xff09; 实验目的&#xff1a;解决防火墙上的接口不足以为其他区域服务的问题&#xff0c;比方说防火墙上只有两个接口&#xff0c;但是有三个区域&#xff0c;那这个实验的目的为了解决防火墙上的接口不足以为多区域提…

H3C防火墙基础配置2-配置安全策略

1 安全策略简介 安全策略对报文的控制是通过安全策略规则实现的&#xff0c;规则中可以设置匹配报文的过滤条件&#xff0c;处理报文的动作和对于报文内容进行深度检测等功能。 &#xff08;1&#xff09;规则的名称和编号 安全策略中的每条规则都由唯一的名称和编号标识。名称…

H3C防火墙-安全域配置举例

1. 组网需求 某公司以 Device 作为网络边界安全防护设备&#xff0c;连接公司内部网络和 Internet。公司只对内部提供Web 服务&#xff0c;不对外提供这些服务。现需要在设备上部署安全域&#xff0c;并基于以下安全需求进行域间策略 的配置。 • 与接口 GigabitEthernet1/0/1 …

Firewalld防火墙实例配置

文章目录 环境拓扑需求描述一、环境配置二、防火墙配置1、在网站服务器上配置防火墙2、网关服务器配置防火墙3、企业内网访问外网web服务器4、外网web服务器访问企业内部网站服务器 三、总结问题总结解决方案 环境拓扑 需求描述 1、 网关服务器连接互联网网卡ens33地址为100.1…

【Linux】配置网络和firewall防火墙(超详细介绍+实战)

&#x1f947;&#x1f947;【Liunx学习记录篇】&#x1f947;&#x1f947; 篇一&#xff1a;【Linux】VMware安装unbuntu18.04虚拟机-超详细步骤(附镜像文件&#xff09; 篇二&#xff1a;【Linux】ubuntu18.04系统基础配置及操作 篇三&#xff1a;【Linux】用户与组的操作详…

防火墙配置

防火墙&#xff08;Firewall&#xff09;&#xff0c;也称防护墙。它是一种位于内部网络与外部网络之间的网络安全系统。一项信息安全的防护系统&#xff0c;依照特定的规则&#xff0c;允许或是限制传输的数据通过。防火墙对于我们的网络安全的重要性不言而喻 但是在实际的开发…

H3C防火墙-安全策略典型配置举例

基于 IP 地址的安全策略配置举例 1.组网需求 • 某公司内的各部门之间通过 Device 实现互连&#xff0c;该公司的工作时间为每周工作日的 8 点到 18点。 • 通过配置安全策略规则&#xff0c;允许总裁办在任意时间、财务部在工作时间通过 HTTP 协议访问财务数据库服务器的 Web…

华为防火墙配置教程

01 了解防火墙基本机制 配置防火墙之前请了解防火墙基本工作机制。 1.1 什么是防火墙 防火墙是一种网络安全设备&#xff0c;通常位于网络边界&#xff0c;用于隔离不同安全级别的网络&#xff0c;保护一个网络免受来自另一个网络的攻击和入侵。这种“隔离”不是一刀切&#x…

防火墙基本配置

防火墙 种类 1.包过滤技术 「 静态防火墙 动态防火墙 」 netfilter 真正的配置 位于linux内核的包过滤功能体系 称为linux防火墙的“内核态” iptables 防火墙的配置 工具 主要针对 网络层 针对IP数据包 「体现在对包的IP地址、端口等信息处理」 链表结构 链 ---- 容纳 规则…

防火墙详解(三)华为防火墙基础安全策略配置(命令行配置)

实验要求 根据实验要求配置防火墙&#xff1a; 合理部署防火墙安全策略以及安全区域实现内网用户可以访问外网用户&#xff0c;反之不能访问内网用户和外网用户均可以访问公司服务器 实验配置 步骤一&#xff1a;配置各个终端、防火墙端口IP地址 终端以服务器为例&#x…

防火墙基础配置

状态防火墙 状态检测防火墙&#xff08;Stateful Firewall&#xff09;是一种网络安全设备&#xff0c;它可以检测和过滤网络流量&#xff0c;以保护网络不受未经授权的访问和攻击。 与传统的包过滤防火墙不同&#xff0c;状态检测防火墙可以跟踪网络连接的状态&#xff0c;并…