Java 线程池的奥秘:让你的代码跑得像火箭!

欢迎来到Java线程池的奇幻世界!如果你曾经觉得Java代码跑得像蜗牛,或者你的应用程序偶尔像是喝醉了酒,那你可能需要了解一下Java线程池的秘密武器!今天我们就来深入浅出地揭开线程池的神秘面纱,顺便拯救你的应用程序于水火之中。

什么是线程池?

先来个小故事:假设你是一家包子铺的老板。突然某天来了100个顾客,每个顾客都要现包现蒸的包子。如果你只有一个厨师,那这个厨师会累得吐血,而顾客们也会饿得发慌。聪明的你决定雇佣多个厨师,这样可以同时处理多个订单。但是,雇太多厨师也不划算,他们会在没有订单的时候无所事事,白吃白喝。

线程池就是这样一个聪明的“厨师管理器”。它可以有效地管理多个线程,避免频繁创建和销毁线程带来的开销,同时还可以根据需要动态调整线程数量,让线程的使用更加高效。

线程池的基本原理

Java线程池是通过java.util.concurrent包中的Executor框架实现的。最常用的线程池实现是ThreadPoolExecutor。它的工作原理就像一个高度组织化的包子铺:

  • 核心线程数(corePoolSize):线程池中始终保持的最少线程数。即使这些线程是空闲的,也不会被销毁。
  • 最大线程数(maximumPoolSize):线程池中允许的最大线程数。当活跃线程数达到这个值后,新的任务将会被拒绝,除非有空闲线程。
  • 任务队列(workQueue):当所有核心线程都在忙碌时,新任务会被放入这个队列等待执行。
  • 线程工厂(threadFactory):用于创建新线程,可以自定义线程的属性,比如名称、优先级等。
  • 拒绝策略(handler):当任务太多而无法处理时,采取的策略。比如直接丢弃任务、抛出异常、或是交给其他线程池处理。

线程池的创建和使用

我们通过几种不同方式来创建线程池:

FixedThreadPool:固定大小的线程池,适用于负载相对稳定的场景。

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);

CachedThreadPool:根据需要创建新线程的线程池,适用于执行很多短期异步任务的小系统或负载较轻的服务器。

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

ScheduledThreadPool:定期执行任务的线程池,适用于需要周期性执行任务的场景。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);

SingleThreadExecutor:单线程的线程池,适用于需要顺序执行任务的场景。

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

线程池的妙用

让我们通过几个实际例子来看看线程池的妙用。

示例一:处理大量并发任务

假设你正在开发一个需要处理大量并发请求的Web服务器。使用线程池可以显著提高服务器的响应能力:

public class WebServer {private final ExecutorService threadPool = Executors.newFixedThreadPool(10);public void handleRequest(Runnable requestHandler) {threadPool.execute(requestHandler);}public void shutdown() {threadPool.shutdown();}
}
示例二:定期任务调度

假设你需要一个任务每隔一段时间执行一次,ScheduledThreadPool可以帮你搞定:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);Runnable task = () -> System.out.println("执行定期任务:" + new Date());scheduler.scheduleAtFixedRate(task, 0, 10, TimeUnit.SECONDS);

线程池的高级用法

除了基本用法,Java线程池还有很多高级特性,让我们来逐一探讨。

自定义线程工厂

你可以自定义线程的创建逻辑,比如给线程设置名字或优先级:

ThreadFactory customThreadFactory = new ThreadFactory() {private final AtomicInteger threadNumber = new AtomicInteger(1);@Overridepublic Thread newThread(Runnable r) {Thread thread = new Thread(r);thread.setName("CustomThread-" + threadNumber.getAndIncrement());return thread;}
};ExecutorService customThreadPool = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(),customThreadFactory
);
自定义拒绝策略

当线程池无法处理更多任务时,你可以自定义拒绝策略:

RejectedExecutionHandler customHandler = new RejectedExecutionHandler() {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {System.out.println("任务被拒绝:" + r.toString());}
};ExecutorService customThreadPoolWithHandler = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(10),Executors.defaultThreadFactory(),customHandler
);
动态调整线程池大小

你可以根据系统的负载动态调整线程池的大小:

ThreadPoolExecutor dynamicThreadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();dynamicThreadPool.setCorePoolSize(5);
dynamicThreadPool.setMaximumPoolSize(10);

线程池的性能优化

线程池的配置和优化是一门艺术。以下是一些优化技巧:

  1. 合理设置核心线程数:核心线程数应根据系统的CPU核心数和任务的性质来设置。如果任务是CPU密集型,核心线程数可以设置为CPU核心数;如果任务是IO密集型,可以设置为CPU核心数的2倍或更多。

  2. 选择合适的任务队列:常用的任务队列有LinkedBlockingQueueSynchronousQueueArrayBlockingQueue。不同的队列有不同的性能特点,需要根据实际需求选择。

  3. 监控线程池:通过ThreadPoolExecutor的监控方法(如getPoolSize()getActiveCount()getCompletedTaskCount()等)可以获取线程池的运行状态,帮助你及时调整配置。

    System.out.println("当前线程数:" + dynamicThreadPool.getPoolSize());
    System.out.println("正在执行的任务数:" + dynamicThreadPool.getActiveCount());
    System.out.println("已完成的任务数:" + dynamicThreadPool.getCompletedTaskCount());
    

    小结

    Java线程池是一个强大且灵活的工具,能够显著提高应用程序的性能和可扩展性。通过合理地配置和使用线程池,你可以让你的代码跑得像火箭一样快,再也不用担心慢如蜗牛的执行速度。希望这篇博客能帮助你更好地理解和应用Java线程池,让你的代码效率翻倍!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/23875.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python报错】已解决TypeError: can only concatenate str (not “int“) to str

成功解决“TypeError: can only concatenate str (not “int”) to str”错误的全面指南 一、引言 在Python编程中&#xff0c;字符串&#xff08;str&#xff09;和整数&#xff08;int&#xff09;是两种基本的数据类型。然而&#xff0c;当我们尝试将这两种类型的对象进行连…

[matlab]折线图之多条折线如何绘制实心圆作为标记点

使用MarkerFaceColor是标记点填充的颜色&#xff0c;b&#xff0c;表示blue&#xff0c;蓝色 plot(x, a, d--, MarkerFaceColor, b); % 绘制仿真结果的曲线如果一张图多条曲线那么每条曲线需要单独调用一次plot&#xff0c;每个plot间用hold on 连接 plot(x, a, d--, MarkerF…

通配符SSL证书快速申请攻略

一、什么是通配符SSL证书 通配符SSL证书又叫泛域名SSL证书&#xff0c;可以保护一个主域名及其所有二级子域名&#xff0c;并对该级子域名数量无限制&#xff0c;且添加新的该级子域名无须另外付费。 二、通配符SSL证书有哪些优势 1.节省时间和金钱&#xff1a;与购买和安装…

深度学习中的监督学习

深度学习中的监督学习 监督学习&#xff08;Supervised Learning&#xff09;是深度学习中最常见的一种学习方法&#xff0c;它依赖于标注数据集进行训练&#xff0c;通过学习输入数据与其对应的标签之间的映射关系&#xff0c;最终能够对未见过的数据进行准确预测。以下是对深…

Android海外用户增长

目录 文章背景介绍 概念解释&#xff1a; Google FireBase Facebook Appsflyer Tiktok 文章背景介绍 做海外app的【用户增长】功能必经之路&#xff0c;Google的FireBase、AppsFlyer、Facebook、Tiktok&#xff0c;Message等SDK可能都需要接触&#xff0c;以上SDK是我们在…

Spring Boot + URule 实现可视化规则引擎,太优雅了!

Spring Boot URule 实现可视化规则引擎&#xff0c;太优雅了&#xff01; 一、背景二、介绍三、安装使用四、基础概念整体介绍库文件变量库文件常量库文件参数库文件动作库文件规则集向导式规则集脚本式规则集 决策表其他 五、运用场景六、总结 一、背景 前段时间&#xff0c…

2、Tomcat 线程模型详解

2、Tomcat 线程模型详解 Tomcat I/O模型详解Linux I/O模型详解I/O要解决什么问题Linux的I/O模型分类 Tomcat支持的 I/O 模型Tomcat I/O 模型如何选型 网络编程模型Reactor线程模型单 Reactor 单线程单 Reactor 多线程主从 Reactor 多线程 Tomcat NIO实现Tomcat 异步IO实现 Tomc…

CentOs7 JDK21 安装

CentOs7 JDK21 安装 准备工作 先检查系统是否之前已经安装了jdk 。如果已经安装的话需要卸载。 方式一&#xff1a;使用压缩包的方式 下载jdk21的压缩包 https://www.oracle.com/java/technologies/downloads/ 将下载的gz压缩包上传到服务器并解压 # 创建文件夹 (你可以自…

java web如何调用py脚本文件

Controller public class IndexController {RequestMapping("/pythonTest")ResponseBodypublic String pythonTest(){// 假设你的Python脚本名为script.pyString pythonScriptPath "D:\\project\\c1\\hello.py";ProcessBuilder processBuilder new Proce…

C51学习归纳6 --- UART串口数据通信

这一部分我认为是十分重要的&#xff0c;没有了数据的传输&#xff0c;我们做的很多事情将是没有意义的。我们一般利用串口做两件事&#xff0c;一是单片机向电脑发送信息&#xff0c;二是单片机接收电脑的信息。 一、UART原理 TXD:发送信息通道,RXD: 接收信息通道。我发送你接…

Nginx之初识

1.Nginx概述 Nginx是一个高性能的反向代理和Web服务器软件&#xff0c;因其系统资源消耗低、运行稳定且具有高性能的并发处理能力等特性&#xff0c;在互联网企业中得到广泛的应用。 2.Nginx特性 1.访问路由 现今大型网站的请求量早已不是单一Web服务器可以支撑的了。单一入口…

微服务+分库分表的自增主键ID该如何设计?

一. 前言 分布式ID 是分布式系统里面非常重要的一个组成部分&#xff0c;那么我们在设计分布式ID的时候&#xff0c;需要考虑什么问题呢&#xff1f; ❓简单结构下是怎么实现 ID 的控制的&#xff1f; 单实例系统 &#xff1a;通过时间戳&#xff0c;系统内自增&#xff0c;上…

[Algorithm][动态规划][两个数组的DP][正则表达式匹配][交错字符串][两个字符串的最小ASCII删除和][最长重复子数组]详细讲解

目录 1.正则表达式匹配1.题目链接2.算法原理详解3.代码实现 2.交错字符串1.题目链接2.算法原理详解3.代码实现 3.两个字符串的最小ASCII删除和1.题目链接2.算法原理详解3.代码实现 4.最长重复子数组1.题目链接2.算法原理详解3.代码实现 1.正则表达式匹配 1.题目链接 正则表达…

《令狐带你阅读JDK源码之简单集合ArrayList》

文章目录 Java简单集合ArrayList继承体系源码解析 总结 大家好哈&#xff0c;欢迎来到令狐小哥本期专栏&#xff0c;这期专栏主要是带着大家阅读JDK源码&#xff0c;我会分几期篇幅来介绍这个jdk源码、会进行剖析、梳理&#xff0c;欢迎大家指正阅读。后面我会配套自己的视频进…

计算机网络 期末复习(谢希仁版本)第2章

物理层考虑的是怎样才能在连接各种计算机的传输媒体上传输数据比特流&#xff0c;而不是指具体的传输媒体。4 个特性&#xff1a; 机械特性&#xff1a;指明接口所用接线器的形状和尺寸、引线数目和排列、固定和锁定装置等。 电气特性&#xff1a;指明在接口电缆的各条线上出现…

【python进阶】python图形化编程之美--tkinter模块初探

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

白酒:茅台镇白酒的地域特色与环境优势

茅台镇&#xff0c;位于中国贵州省仁怀市&#xff0c;因其与众不同的自然环境和酿酒工艺而成为世界著名的白酒产区。作为茅台镇的品牌&#xff0c;云仓酒庄豪迈白酒以其卓着的品质和口感赢得了广大消费者的喜爱。而这一切&#xff0c;都离不开茅台镇的地域特色和环境优势。 茅台…

构建LangChain应用程序的示例代码:20、使用LangChain的SQLDatabase包装器连接到Databricks运行时并执行查询操作教程

Databricks SQL 数据库连接 概述 这个笔记本介绍了如何使用LangChain的SQLDatabase包装器连接到Databricks运行时和Databricks SQL。 内容分为三个部分&#xff1a;安装和设置、连接到Databricks以及示例。 安装和设置 !pip install databricks-sql-connector # 安装Datab…

Python 知识图谱补全,Knowledge Graph Completion,基于大模型的知识图谱补全,基于LLMs的KGC任务

今天讲一篇文章《Exploring Large Language Models for Knowledge Graph Completion》 &#xff0c;这篇文章主题&#xff1a;基于大模型做知识图谱补全 1.文章主要思想&#xff1a; 本章描述知识图谱补全中的三个任务&#xff1a;三元组分类、关系预测和实体(链接)预测&…

C++初阶学习第十一弹——探索STL奥秘(六)——深度刨析list的用法和核心点

前言&#xff1a; 在前面&#xff0c;我们已经学习了STL中的string和vector&#xff0c;现在就来讲解STL中的最后一个部分——list的使用及其相关知识点&#xff0c;先说明一点&#xff0c;因为我们之前已经讲过了string和vector的接口函数等用法&#xff0c;list的这些用法与它…