1、ThreadPoolExecutor 类: 它是线程池管理器的核心类,卖力创建、销毁和管理线程。

核心方法:

execute(Runnable command): 将任务提交给线程池实行。
shutdown(): 开始关闭线程池,不再接管新任务,但会连续实行已提交的任务。
shutdownNow(): 立即关闭线程池,并考试测验停滞所有正在实行的任务。

关键属性:

was线程池jsp空白java线程池实现道理以及运用场景解释 React

corePoolSize: 核心线程数,纵然没有任务,也会保持这些线程存活。
maximumPoolSize: 最大线程数,当任务行列步队满且核心线程数不敷时,会创建新的线程,但不超过最大线程数。
keepAliveTime: 空闲线程的存活韶光,当线程数超过核心线程数时,空闲线程会存活一段韶光,如果超过该韶光,则会被回收。
workQueue: 任务行列步队,用于存放等待实行的任务。
threadFactory: 线程工厂,用于创建新的线程。
handler: 谢绝策略,当线程池无法处理新任务时,会调用谢绝策略处理该任务。

2、Worker 类: 实际实行任务的线程类,每个 Worker 线程都持有一个 Runnable 工具,用来实行任务。

关键方法:

run(): 线程启动后,会调用该方法,从任务行列步队中获取任务并实行。
isLocked(): 判断当前哨程是否正在实行任务。
processWork(Runnable task): 实行任务,并处理任务实行完后的状态。

3、BlockingQueue 接口: 任务行列步队,用于存放等待实行的任务。

常用实现:

ArrayBlockingQueue: 基于数组实现的有界行列步队,FIFO 顺序。
LinkedBlockingQueue: 基于链表实现的无界行列步队,FIFO 顺序。
SynchronousQueue: 同步队列,每个插入操作都须要等待一个相应的移除操作。

4、ThreadFactory 接口: 线程工厂,用于创建新的线程。

常用实现:

Executors.defaultThreadFactory(): 默认的线程工厂,用于创建新的线程。
自定义线程工厂: 可以自定义线程名、线程优先级等属性。

5、RejectedExecutionHandler 接口: 谢绝策略,当线程池无法处理新任务时,会调用谢绝策略处理该任务。

常用实现:

AbortPolicy: 直接抛出 RejectedExecutionException 非常。
CallerRunsPolicy: 由调用者线程实行任务。
DiscardPolicy: 丢弃任务。
DiscardOldestPolicy: 丢弃行列步队中最旧的任务。

二、线程池事情流程

1、提交任务: 当调用 execute(Runnable command) 方法提交任务时,线程池会先判断当前哨程池的状态:

线程数 < corePoolSize: 创建一个新的核心线程实行任务。
线程数 >= corePoolSize: 将任务放入任务行列步队。
任务行列步队已满 && 线程数 < maximumPoolSize: 创建一个新的非核心线程实行任务。
任务行列步队已满 && 线程数 >= maximumPoolSize: 调用谢绝策略处理该任务。

2、实行任务: Worker 线程会从任务行列步队中获取任务并实行,实行完成后会再次考试测验从行列步队中获取任务。

3、管理线程: 线程池会根据任务情形动态调度线程数量:

空闲线程超过 keepAliveTime: 回收空闲线程。
任务增加: 创建新的线程处理任务。

4、关闭线程池: 当调用 shutdown() 或 shutdownNow() 方法时,线程池会停滞接管新的任务,并等待所有已提交的任务实行完毕后关闭线程池。

jdk中四种线程池利用场景解释

1、newFixedThreadPool(int nThreads)

场景: 适宜实行须要固天命量线程的任务,例如处理网络要求、数据库连接池等。

优点:

线程数量固定,不会涌现创建过多的线程导致资源耗尽的情形。
可以掌握并发程度,避免资源竞争和去世锁。

缺陷:

线程池大小固定,无法根据任务负载动态调度。
当任务量大时,可能会造成任务积压。

把稳事变:

线程池大小固定,如果任务过多,会造成任务积压,导致相应缓慢。
当所有线程都处于繁忙状态时,新任务会被放入行列步队等待。

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class FixedThreadPoolExample { public static void main(String[] args) { // 创建固定大小为 5 的线程池 ExecutorService executor = Executors.newFixedThreadPool(5); // 提交 10 个任务 for (int i = 0; i < 10; i++) { executor.execute(() -> { System.out.println(Thread.currentThread().getName() + " is executing task"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } executor.shutdown(); }}

2、newCachedThreadPool()

场景: 适宜实行大量短韶光任务,例如处理 HTTP 要求、文件上传下载等。

优点:

可以根据须要动态创建线程,避免资源摧残浪费蹂躏。
能够快速相应大量短韶光任务。

缺陷:

可能创建过多的线程,导致系统资源耗尽。
频繁创建销毁线程,会造成性能损耗。

把稳事变:

可能会创建大量线程,导致系统资源耗尽。
线程空闲超过 60 秒就会被回收,频繁创建销毁线程,会造成性能损耗。

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class CachedThreadPoolExample { public static void main(String[] args) { // 创建可缓存线程池 ExecutorService executor = Executors.newCachedThreadPool(); // 提交 10 个任务 for (int i = 0; i < 10; i++) { executor.execute(() -> { System.out.println(Thread.currentThread().getName() + " is executing task"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } executor.shutdown(); }}

3、newSingleThreadExecutor

场景: 适宜实行串行任务,例如处理数据库操作、文件读写等。

优点:

担保任务按顺序实行。
避免多线程竞争资源。

缺陷:

无法利用多核 CPU 的上风,效率较低。
当单个任务实行韶光过永劫,会影响其他任务的实行。

把稳事变:

仅创建单个线程,所有任务都由该线程串行实行。

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class SingleThreadExecutorExample { public static void main(String[] args) { // 创建单线程线程池 ExecutorService executor = Executors.newSingleThreadExecutor(); // 提交 10 个任务 for (int i = 0; i < 10; i++) { executor.execute(() -> { System.out.println(Thread.currentThread().getName() + " is executing task"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } }); } executor.shutdown(); }}

4、newScheduledThreadPool(int corePoolSize)

场景: 适宜实行定时任务和周期性任务,例如定期数据备份、定时清理缓存等。

优点:

支持定时任务和周期性任务实行。
可以灵巧掌握任务实行韶光。

缺陷:

须要手动管理任务韶光间隔。
当任务实行韶光过永劫,可能会影响其他任务的实行。

把稳事变:

须要设置核心线程数和任务实行的韶光间隔。
建议利用 scheduleAtFixedRate 或 scheduleWithFixedDelay 方法来实行定时任务。

import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;public class ScheduledThreadPoolExample { public static void main(String[] args) { // 创建带定时功能的线程池 ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); // 定时任务:每隔 1 秒实行一次 executor.scheduleAtFixedRate(() -> { System.out.println(Thread.currentThread().getName() + " is executing scheduled task"); }, 1, 1, TimeUnit.SECONDS); executor.shutdown(); }}

线程池运行情形监控

一、开源项目

1、Zimug-Monitor-ThreadPool

实现事理:

利用 Java Agent 技能在程序启动时修正 ThreadPoolExecutor 类的字节码。
在 ThreadPoolExecutor 的布局函数中添加代码,将新建的线程池添加到一个全局凑集中。
通过定时任务监控全局凑集中的所有线程池,获取状态信息并输出到日志或图形界面。

上风:

专注于线程池监控,供应丰富的线程池状态信息,包括活动线程数、行列步队大小、已完成任务数量、核心线程数、最大线程数、保持活动韶光等。
可以根据监控信息进行综合剖析,判断线程池是否处于过载、行列步队是否满等情形,并输出警告信息。

劣势:

须要利用 Java Agent 技能,须要修处死式的字节码,可能须要重新编译程序。
监控线程池的性能影响可能会比较大,由于须要不断地获取线程池的状态信息。

2、JavaMelody

实现事理:

利用 Java Agent 技能,在程序启动时修正部分核心类,例如 ClassLoader、Thread 等。
通过 AOP 技能拦截方法调用,获取程序运行的性能指标,例如 CPU 利用率、内存占用、方法实行韶光等。
供应 Web 界面展示性能指标,并供应一些诊断和剖析工具。

上风:

功能强大,可以监控程序的各个方面,包括线程池、内存、CPU、网络等。
供应丰富的诊断工具,可以帮助用户剖析程序性能问题。
供应 Web 界面,方便用户查看和剖析监控数据。

劣势:

监控范围比较广,可能导致监控数据比较多,增加剖析难度。
性能影响比较大,由于须要拦截方法调用,获取性能指标。

3、Spring Boot Actuator

事理:

Spring Boot Actuator 供应了 Endpoint 机制,可以暴露程序的运行状态信息,包括线程池信息。
Actuator 利用 Micrometer 库网络性能指标,并通过 HTTP 协议暴露指标数据。

监控线程池的事理:

集成 Micrometer 库: Spring Boot Actuator 默认集成 Micrometer 库,用于网络程序的性能指标。
创建 ThreadPoolMetrics 工具: Micrometer 库供应了 ThreadPoolMetrics 类,用于网络线程池的性能指标。
注册 ThreadPoolMetrics 工具: 将 ThreadPoolMetrics 工具注册到 MeterRegistry 中,并关联到相应的线程池。
利用 Endpoint 暴露指标数据: Actuator 供应了 /actuator/metrics 端点,可以获取程序的性能指标数据,包括线程池的指标数据。

优点:

大略易用: Spring Boot Actuator 供应了开箱即用的线程池监控功能,无需额外配置。
集成方便: Actuator 与 Micrometer 库集成,可以方便地网络其他性能指标。
功能强大: Actuator 供应了丰富的端点,可以获取程序的各种运行状态信息,包括线程池、内存、CPU 等。
可扩展性强: Actuator 可以自定义 Endpoint,知足各种监控需求。

缺陷:

性能影响: Actuator 的监控机制会对程序性能造成一定影响,特殊是高性能程序。
依赖 Spring Boot: Actuator 只能在 Spring Boot 项目中利用。
监控范围有限: Actuator 紧张监控 Spring Boot 运用程序,对其他程序的监控功能有限。

=====1、开启监控management.endpoint.metrics.enabled=true=====2、启动 Spring Boot 运用程序后,访问 http://localhost:8080/actuator/metrics,可以获取运用程序的性能指标数据,包括线程池的指标数据。
{ "names": [ "system.cpu.usage", "jvm.memory.used", "jvm.memory.max", "jvm.threads.count", "http.server.requests", "threadpool.executor.active", "threadpool.executor.queue.size", "threadpool.executor.completed", "threadpool.executor.rejected" ]}

4、Prometheus with Grafana

二、自定义实现

ThreadPoolMonitorAgent 类: 与之前代码基本同等,利用 Java Agent 技能监控所有创建的 ThreadPoolExecutor 线程池。
monitorThreadPool() 方法:添加了更多监控指标的获取,包括 corePoolSize、maximumPoolSize、keepAliveTime。
添加了线程池状态判断,包括 isRunning(判断线程池是否处于运行状态)和 isSaturated(判断线程池是否处于饱和状态)。
打印或记录监控信息,包括线程池状态、监控指标和综合剖析结果。
综合剖析线程池运行情形,根据监控指标判断线程池是否处于过载、行列步队是否满等情形,并输出警告信息。

import java.lang.instrument.Instrumentation;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.HashSet;import java.util.Set;import java.util.concurrent.BlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicLong;public class ThreadPoolMonitorAgent { private static final Set<ThreadPoolExecutor> monitoredPools = new HashSet<>(); public static void premain(String agentArgs, Instrumentation inst) { inst.addTransformer((loader, className, classfileBuffer, protectionDomain) -> { if (className.equals("java/util/concurrent/ThreadPoolExecutor")) { return new ClassFileTransformer() { @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { try { return instrumentClass(classfileBuffer); } catch (Exception e) { e.printStackTrace(); return classfileBuffer; } } }.transform(loader, className, null, protectionDomain, classfileBuffer); } return classfileBuffer; }); } private static byte[] instrumentClass(byte[] classfileBuffer) throws Exception { // 利用 ASM 或其他字节码操作库修正 ThreadPoolExecutor 类 // 在布局函数中添加代码来监控线程池 // 例如,将线程池添加到 monitoredPools 凑集中 return classfileBuffer; // 这里须要实际修正字节码 } // 监控线程池状态的代码 public static void monitorThreadPool() { for (ThreadPoolExecutor pool : monitoredPools) { // 获取线程池状态信息 int activeCount = pool.getActiveCount(); int queueSize = pool.getQueue().size(); long completedTaskCount = pool.getCompletedTaskCount(); int corePoolSize = pool.getCorePoolSize(); int maximumPoolSize = pool.getMaximumPoolSize(); long keepAliveTime = pool.getKeepAliveTime(TimeUnit.SECONDS); // 判断线程池状态 boolean isRunning = !pool.isShutdown() && !pool.isTerminated(); boolean isSaturated = queueSize >= maximumPoolSize; // 打印或记录监控信息 System.out.println("ThreadPool: " + pool); System.out.println("Status: " + (isRunning ? "RUNNING" : "SHUTDOWN")); System.out.println("Active Count: " + activeCount); System.out.println("Queue Size: " + queueSize); System.out.println("Completed Task Count: " + completedTaskCount); System.out.println("Core Pool Size: " + corePoolSize); System.out.println("Maximum Pool Size: " + maximumPoolSize); System.out.println("Keep Alive Time: " + keepAliveTime + " seconds"); System.out.println("Saturated: " + isSaturated); System.out.println("--------------------------------------"); // 综合剖析线程池运行情形 if (activeCount >= maximumPoolSize) { System.out.println("WARNING: ThreadPool is overloaded. Consider increasing maximumPoolSize."); } if (queueSize > 0 && isSaturated) { System.out.println("WARNING: ThreadPool queue is full. Tasks may be rejected."); } } }}// 在程序启动时添加 agent 参数:// -javaagent:path/to/ThreadPoolMonitorAgent.jar

第三方线程池框架Apache Commons Pool2: 供应了工具池管理机制,可以用于线程池管理。
Google Guava: 包含 ListeningExecutorService 等类,供应更丰富的线程池监控和掌握功能。
Spring Framework: 供应了 TaskExecutor 接口,可以利用 Spring 的 ThreadPoolTaskExecutor 实现线程池管理,并与 Spring 容器集成。
Hutool java程序堆栈信息线程池剖析

1、利用 jstack 命令

导出堆栈信息: 在命令行中利用 jstack 命令,并指定 Java 进程的 PID,例如:jstack 12345 > thread_dump.txt

2、利用 JProfiler 或 VisualVM 等性能剖析工具

获取线程堆栈信息: 利用这些工具连接到 Java 进程,并选择 "Threads" 或 "Thread Dump" 视图,可以查看所有线程的堆栈信息。
剖析线程池状态: 这些工具常日供应更直不雅观的视图,可以更方便地识别线程池线程、剖析线程状态、查看任务实行逻辑以及探求去世锁。
天生报告: 这些工具可以天生包含线程堆栈信息和其他性能数据的报告,方便分享给其他团队成员。

3、在线工具

https://gceasy.io/index.jsp

https://github.com/PerfMa/XPocket

https://arthas.aliyun.com/doc/