线程池-线程池分类

线程池分类 

  1. FixedThreadPool:固定大小线程池,线程数量固定,不会自动扩容或缩容。

  2. CachedThreadPool:缓存线程池,线程数量不固定,根据需要自动扩容或缩容。适用于执行大量短时间任务的场景。

  3. SingleThreadPool:单线程线程池,只有一个线程在工作,保证任务按顺序执行。

  4. ScheduledThreadPool:定时任务线程池,用于执行定时任务和周期性任务。

  5. WorkStealingPool:工作窃取线程池,每个线程都有自己的工作队列,当某个线程完成自己的任务后,会从其他线程的队列中偷取任务来执行,提高任务执行效率。

  6. ForkJoinPool:分治任务线程池,可以将一个大任务拆分成多个小任务并行执行,并将结果合并,适用于处理大规模的计算任务。

 newFixedThreadPool

     它创建一个具有固定数量线程的线程池。这意味着在任何给定的时间,线程池中最多只能同时执行固定数量的任务。

下面是一个示例代码:

ExecutorService executor = Executors.newFixedThreadPool(5);for (int i = 0; i < 10; i++) {Runnable worker = new MyRunnable(i);executor.execute(worker);
}executor.shutdown();
while (!executor.isTerminated()) {
}System.out.println("所有任务执行完毕");

     在这个示例中,我们创建了一个固定数量为5的线程池,并提交了10个任务到线程池中执行。每个任务都是一个MyRunnable对象,它是一个实现了Runnable接口的自定义类。executor.execute(worker)将每个任务提交给线程池执行。

    executor.shutdown()用于关闭线程池,不再接受新任务。然后使用executor.isTerminated()来检查线程池中的任务是否全部执行完毕,直到全部执行完毕后跳出循环。

最后,我们打印出"所有任务执行完毕"的信息。

      使用newFixedThreadPool创建线程池的好处是可以限制同时执行的任务数量,避免线程过多造成的性能问题。当所有任务执行完毕后,线程池可以重用线程来执行新的任务,而不需要每次都创建新的线程。这样可以减少线程创建和销毁的开销,提升程序的性能。

newCachedThreadPool

       newCachedThreadPool是java.util.concurrent.Executors类中提供的一个线程池创建方法。它的原理是根据需要创建线程来执行任务,如果线程池中有空闲线程,则复用空闲线程执行任务;如果线程池中没有空闲线程,则创建新的线程来执行任务。同时,如果线程空闲时间超过60秒,则会被回收,从而适应任务的变化。

下面是代码示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {// 创建一个线程池,使用newCachedThreadPool方法ExecutorService executorService = Executors.newCachedThreadPool();// 提交任务给线程池executorService.submit(new Task("Task 1"));executorService.submit(new Task("Task 2"));executorService.submit(new Task("Task 3"));// 关闭线程池executorService.shutdown();}static class Task implements Runnable {private String name;public Task(String name) {this.name = name;}@Overridepublic void run() {System.out.println("Task " + name + " is running in thread: " + Thread.currentThread().getName());}}
}

     该示例中,首先创建了一个使用newCachedThreadPool方法创建的线程池对象executorService。然后,我们提交了三个任务给线程池去执行。每个任务都是一个Task对象,该对象实现了Runnable接口,重写了run方法,用来定义具体的任务逻辑。在run方法中,我们打印了当前任务的名称以及执行任务的线程名称。

最后,我们调用shutdown方法关闭线程池,等待所有任务执行完毕。

由于使用了newCachedThreadPool方法创建的线程池是一个无界线程池,所以可以执行任意数量的任务。如果线程池中有空闲线程,任务会被分配给空闲线程执行;如果没有空闲线程,会创建新的线程来执行任务。同时,如果线程空闲时间超过60秒,线程会被回收,从而适应任务的变化。

newSingleThreadExecutor

      newSingleThreadExecutor是Java中ExecutorService接口的一个实现类,它创建一个只有一个线程的线程池。该线程池只会用一个线程来执行任务,确保任务按照它们被提交的顺序依次执行,即任务将会顺序执行而不会并发执行。

下面给出一个示例代码:

ExecutorService executor = Executors.newSingleThreadExecutor();executor.execute(new Runnable() {public void run() {try {// 模拟任务执行Thread.sleep(1000);System.out.println("Task executed");} catch (InterruptedException e) {e.printStackTrace();}}
});executor.shutdown();

解释:

  1. 首先通过Executors.newSingleThreadExecutor()创建一个只有一个线程的线程池。

  2. 调用executor.execute()方法提交一个任务(表示为一个Runnable对象)。这里的任务是模拟执行了一段耗时1秒的操作。

  3. 然后调用executor.shutdown()方法来关闭线程池。注意,这里的关闭操作是异步的,即会等待所有任务执行完毕后关闭线程池。

由于newSingleThreadExecutor只有一个线程,所以无论提交多少个任务,它们都将按照提交的顺序一个一个地被顺序执行。在上面的示例中,只有一个任务,因此它将会被执行一次,并在执行完毕后输出"Task executed"。

任务提交

     Executor.execute()方法用于提交一个Runnable任务给执行器执行。执行器会立即开始执行任务,并且无法取消或获取任务的结果。

   ExecutorService.submit()方法用于提交一个Runnable或Callable任务给执行器执行,并且返回一个表示任务结果的Future对象。可以通过Future对象来获取任务的执行结果,也可以使用Future对象来取消任务的执行。

线程池调优

      线程池调优是指对线程池的配置和参数进行调整,以达到更好的性能和资源利用效率。

  1. 根据实际需求配置线程池大小:线程池大小应该根据系统的负载情况来设定,太小会导致任务等待时间过长,太大则会增加系统负担。可以根据系统的并发请求量和处理能力来动态调整线程池的大小。

  2. 设置合理的阻塞队列大小:线程池的阻塞队列可以用于缓存等待执行的任务,但是过大的队列可能会占用过多的内存,导致系统资源浪费。应根据实际情况选择合适的队列大小,一般来说,有界队列比无界队列更可控,可以避免无限制的堆积。

  3. 考虑任务执行时间和响应时间:如果大部分任务执行时间较短,可以适当增加线程池的大小来提高并发处理能力。如果大部分任务执行时间较长,可以适当减少线程池的大小,以避免资源浪费。

  4. 使用合适的线程池类型:Java中常用的线程池类型有FixedThreadPool、CachedThreadPool和ScheduledThreadPool等,选择合适的线程池类型可以更好地适应任务的特性和需求。

  5. 监控和调整:通过监控线程池的运行状况,可以及时发现并解决问题,例如线程池的饱和状态、活动线程数、任务等待时间等。可以使用一些监控工具和框架来帮助收集和分析线程池的数据,从而做出有针对性的调整。

  6. 合理处理任务拒绝策略:当线程池满了并且队列也满了时,可以使用合适的任务拒绝策略来处理超出处理能力的任务。常用的策略有丢弃任务、调用者运行和抛出异常等,可以根据实际需求选择合适的策略。

线程池监控

  1. 线程池监控指标:可以通过调用ThreadPoolExecutor类的方法来获取线程池的各项指标,比如getPoolSize()可以获取线程池的当前线程数,getActiveCount()可以获取正在执行任务的线程数,getCompletedTaskCount()可以获取已经完成的任务数等。

  2. 线程池状态:可以通过调用ThreadPoolExecutor类的方法来获取线程池的当前状态,比如isShutdown()可以判断线程池是否已经被关闭,isTerminated()可以判断线程池是否已经完全终止。

  3. 监控任务执行情况:可以通过实现ThreadPoolExecutor类的子类,重写其beforeExecute()和afterExecute()方法来监控任务的执行情况。beforeExecute()方法会在每个任务执行之前调用,可以在该方法中记录任务开始执行的时间,afterExecute()方法会在每个任务执行之后调用,可以在该方法中记录任务执行结束的时间,并计算任务执行的时长。

  4. 监控线程池异常信息:可以通过实现ThreadPoolExecutor类的子类,重写其afterExecute()方法,在该方法中捕获任务执行过程中的异常信息,并进行处理。

  5. 使用管理工具:Java也提供了一些管理工具,如JConsole、VisualVM等,可以用来对线程池进行监控和管理。

总结 

     线程池有三种分类,分别是固定大小线程池、可缓存线程池和定时任务线程池。

  1. 固定大小线程池(FixedThreadPool): 这种线程池的核心线程数量是固定的,不会随着任务的增加而增加。当有新任务到达时,如果当前线程池中的线程数量小于核心线程数量,则直接创建一个新线程来执行任务;如果当前线程数量已经达到核心线程数量,则将新任务放入任务队列中等待执行。当任务队列已满且线程池中的线程都处于繁忙状态时,新任务会由线程池的拒绝策略来处理。

  2. 可缓存线程池(CachedThreadPool): 这种线程池的核心线程数量是0,最大线程数量是无限制的。当有新任务到达时,线程池会尝试复用已有的线程来执行任务,如果没有可用的线程,则创建一个新线程来执行任务。当线程池中的线程空闲时间超过一定时间(默认为60秒),则会被自动销毁。这种线程池适用于执行耗时较短的任务,任务量较大且随时可能增加的场景。

  3. 定时任务线程池(ScheduledThreadPool): 这种线程池可以执行定时任务和周期性任务。它由一个核心线程池和一个任务队列组成。当有新任务到达时,如果当前线程池中的线程数量小于核心线程数量,则直接创建一个新线程来执行任务;如果当前线程数量已经达到核心线程数量,则将新任务放入任务队列中等待执行。当任务队列已满且线程池中的线程都处于繁忙状态时,新任务会由线程池的拒绝策略来处理。定时任务线程池适用于需要定时执行任务或周期性执行任务的场景。

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

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

相关文章

HttpClient、OKhttp、RestTemplate接口调用对比( Java HTTP 客户端)

文章目录 HttpClient、OKhttp、RestTemplate接口调用对比HttpClientOkHttprestTemplate HttpClient、OKhttp、RestTemplate接口调用对比 HttpClient、OkHttp 和 RestTemplate 是三种常用的 Java HTTP 客户端库&#xff0c;它们都可以用于发送 HTTP 请求和接收 HTTP 响应&#…

微服务学习(黑马)

学习黑马的微服务课程的笔记 导学 微服务架构 认识微服务 SpringCloud spring.io/projects/spring-cloud/ 服务拆分和远程调用 根据订单id查询订单功能 存在的问题 硬编码 eureka注册中心 搭建eureka 服务注册 在order-service中完成服务拉取 Ribbon负载均衡 Nacos注册中心…

水利自动化控制系统平台介绍

水利自动化控制系统平台介绍 在当今社会&#xff0c;水资源的管理和保护日益成为全球关注的重要议题。随着科技的进步和信息化的发展&#xff0c;水利监测系统作为一种集成了现代信息技术、自动化控制技术以及环境监测技术的综合性平台&#xff0c;正在逐步改变传统的水利管理模…

快照技术的基本介绍

目录 一、概述 二、名词解释 三、镜像分离 四、COW 五、ROW 六、参考 一、概述 全球网络存储工业协会 SNIA&#xff08;Storage Networking Industry Association&#xff09;对快照&#xff08;Snapshot&#xff09;的定义是&#xff1a;关于指定数据集合的一个完全可用…

广佛站点导航助手小程序产品使用说明书

一、产品简介 广佛站点导航助手小程序是一款专为广佛地区用户设计的地铁导航工具。通过获取用户的实时位置信息&#xff0c;小程序能够迅速定位并展示离用户最近的三个地铁站点。用户可以通过本小程序轻松查找地铁站点&#xff0c;规划出行路线&#xff0c;提高出行效率。 二、…

【背】蓝桥杯大模板

蓝桥杯大模板 /* 头文件声明区 */ #include <STC15F2K60S2.H>//单片机寄存器专用头文件 #include <Init.h>//初始化底层驱动专用头文件 #include <Led.h>//Led底层驱动专用头文件 #include <Key.h>//按键底层驱动专用头文件 #include <Seg.h>//…

Win11 WSL2 install Ubuntu20.04 and Seismic Unix

Win11系统&#xff0c;先启用或关闭Windows功能&#xff0c;勾选“适用于Linux的Windows子系统”和“虚拟机平台”两项 设置wsl默认版本为wsl2&#xff0c;并更新 wsl --list --verbose # 查看安装版本及内容 wsl --set-default-version 2 # 设置wsl默认版本为wsl2 # 已安装…

Debian 安装 Docker

Debian 安装 Docker。 这是官方安装文档 Install Docker Engine on Debian | Docker DocsLearn how to install Docker Engine on Debian. These instructions cover the different installation methods, how to uninstall, and next steps.https://docs.docker.com/engine/i…

我的 Lisp 学习历程:从新手到熟练掌握

Lisp&#xff0c;作为一种功能强大且具有独特思维方式的编程语言&#xff0c;一直以来都吸引着我。在我的编程之旅中&#xff0c;我决定深入学习 Lisp&#xff0c;并在这个过程中经历了许多挑战和成长。本文将分享我在 Lisp 学习过程中的心路历程。 第一次接触 Lisp&#xff0…

计算机网络——抓取icmp包

前言 本博客是博主用于记录计算机网络实验的博客&#xff0c;如果疏忽出现错误&#xff0c;还望各位指正。 抓包 我们是用Wireshark工具来进行抓包的。 ​在安装时候一路打勾安装即可&#xff0c;不过最后那个因为是英文&#xff0c;一定要看清&#xff0c;点了立即重启&am…

mars3d.MaterialType.Image2修改配置面状:图片2的speed数值实现动画效果说明

摘要&#xff1a; mars3d.MaterialType.Image2修改配置面状&#xff1a;图片2的speed数值实现动画效果说明 前提&#xff1a; 1.在示例中&#xff0c;尝试给mars3d.MaterialType.Image2材质的图片加上speed参数&#xff0c;实现动画效果&#xff0c;但是没有看到流动效果说明…

去掉el-date-picker弹窗默认回显当前月份的方法

打开日期弹窗&#xff0c;默认会显示当前月份&#xff0c;如图 会发现加了穿透&#xff1a;&#xff1a;v-deep 样式也不生效 .el-month-table .today .cell {color: pink&#xff1b;font-weight: 400;}要让 popper-class“xclass” :append-to-body“false” 这俩配合着使用…

界面设计【1】-项目的UI设计css

引言&#xff1a; 本篇博客对简单的css html界面设计做了简要介绍 这篇博客主要就是介绍了做横向项目中&#xff0c;CSS界面设计与优化。 界面设计【1】-项目的UI设计css 1. 什么是css?2. css编程demo3. 可视化效果 1. 什么是css? CSS是层叠样式表&#xff08;Cascading S…

每日一题 — 将 x 减到 0 的最小操作数

思路&#xff1a; 题目要求是让我们从数组的最左端和最右端进行操作&#xff0c;这样的话解题的难度大大提升&#xff0c;我们可以用 正难则反 的思想&#xff1a; 题目中要求是减去数组中的数刚好等于X&#xff0c;我们可以转换成 数组中某一段的和等于 数组的总长减去X(sum -…

Godot插值、贝塞尔曲线和Astar寻路

一、插值 线性插值是采用一次多项式上进行的插值计算&#xff0c;任意给定两个值A和B&#xff0c;那么在A和B之间的任意值可以定义为&#xff1a;P(t) A * (1 - t) B * t&#xff0c;0 < t < 1。 数学中用于线性拟合&#xff0c;游戏应用可以做出跟随效果&#xff08;…

vivado FFT IP核使用

matlab生成正弦函数 采样点数为512&#xff0c;每个采样点位宽为16位&#xff0c;其中最高位为符号为&#xff08;0正&#xff0c;1负&#xff09;。换句话说&#xff0c;如果用ROM存储正弦函数的coe文件的话&#xff0c;ROM ip核的位宽设置为16&#xff0c;深度为512. clear…

5G智慧港口简介(二)

5G 技术赋能智慧港口 5G 标准的制定是一个不断发展和完善的过程:第一版国际标准(Rel-15)已全部完成,第二版增强标准(Rel-16)正在制定中,预计 2020 年 3 月完成,面向演进的 Rel-17 标准已启动技术布局,进入立项规划阶段。 5G 是一张具备大速率、大连接、低时延的网络…

Vue ElementUI el-input-number 改变控制按钮 icon 箭头为三角形

el-input-number 属性 controls-position 值为 right 时&#xff1b; <el-input-number v-model"num" controls-position"right" :min"1" :max"10"></el-input-number>原生效果 修改后效果 CSS 修改 .el-input-number…

【LeetCode热题100】41. 缺失的第一个正数(数组)

一.题目要求 给你一个未排序的整数数组 nums &#xff0c;请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 二.题目难度 困难 三.输入样例 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3…

g++ 13.2.0 编译 C++模块

创建并使用自己的C模块&#xff08;Windows10MSVC&#xff09;-CSDN博客 在这篇文章中使用的是MSVC来编译模块和使用模块的代码&#xff0c;现在换g再来编译一次。 环境&#xff1a; ubuntu 23.10 sharpsharp-vbox ~> g --version g (Ubuntu 13.2.0-4ubuntu3) 13.2.0 C…