多线程-线程池

为什么要使用线程池

      

在Java中使用线程池的主要原因有以下几点:

  1. 提高性能:使用线程池可以减少线程的创建和销毁过程的开销。线程的创建和销毁是比较昂贵的操作,如果每次需要执行任务时都创建一个新线程,会造成系统资源的浪费。而线程池可以在程序启动时就创建一定数量的线程,然后重复使用这些线程来执行多个任务。这样可以减少线程创建和销毁的次数,提高系统的性能。

  2. 控制并发数量:线程池可以控制同时执行的任务数量。通过设置线程池的大小,可以限制并发执行的线程数量,避免系统资源被过度占用,导致整个系统的性能下降。

  3. 提供可管理的线程:线程池提供了一种管理和监视线程的机制。通过使用线程池,可以方便地对线程进行管理,比如动态调整线程池大小、监控线程的运行状态等。

  4. 提供线程复用:线程池可以重复利用已有的线程来执行任务,避免了线程的创建和销毁过程,提高了系统的效率。

  5. 提供任务排队机制:线程池可以提供一个任务队列,用于存放等待执行的任务。当线程池中的线程都在执行任务时,新的任务可以被放入队列中,等待线程空闲时执行。这样可以避免任务因为没有可用线程而被丢弃或者阻塞。

常用的几种线程池以及其中的工作原理

     

在Java中,常用的几种线程池有以下几种:

  1. FixedThreadPool:固定大小的线程池,线程数量固定不变,适合执行长期的任务。如果所有线程都处于繁忙状态,新任务将在队列中等待。

  2. CachedThreadPool:可缓存的线程池,线程数量不固定,适合执行大量的短期任务。如果线程池中有可用的线程,就会重用它;如果没有可用线程,就会创建一个新线程。当线程闲置时间超过60秒时,线程将被终止并从池中移出。

  3. SingleThreadPool:单线程的线程池,只会创建一个线程来执行任务。适合需要顺序执行任务的场景。

  4. ScheduledThreadPool:用于延时或定时执行任务的线程池。可以按照指定的周期来执行任务,或者在指定的延迟时间之后执行任务。

线程池的工作原理如下:

  1. 创建线程池时,会初始化一定数量的线程,这些线程会一直存在,等待任务的到来。

  2. 当有任务提交给线程池时,会从线程池中选择一个空闲的线程来执行任务。如果没有空闲线程,任务将被添加到线程池的任务队列中等待执行。

  3. 如果任务队列已满,且线程池中的线程数未达到线程池的最大线程数限制,线程池会创建一个新的线程来执行任务。

  4. 当线程执行完任务后,会检查任务队列中是否还有等待执行的任务。如果有,继续从任务队列中选择任务来执行。如果没有,线程将进入空闲状态,等待下一个任务的到来。

  5. 当线程池不再接收新的任务时,可以调用shutdown()方法来关闭线程池。关闭线程池后,线程池中的线程会等待任务队列中的任务执行完毕后退出。

线程池启动线程 submit()和 execute()方法有什么不同

      submit()方法和execute()方法都是用于向线程池提交任务的方法,但是它们有一些不同之处:

  1. 返回值不同:submit()方法返回一个Future对象,可以用来获取任务的执行结果或取消任务;而execute()方法没有返回值。

  2. 异常处理不同:submit()方法会捕获任务执行过程中的异常,并将其封装到Future对象中,通过调用Future对象的get()方法可以获取到异常信息;而execute()方法不会捕获任务执行过程中的异常,如果任务发生异常,线程池会将异常抛出到控制台。

  3. 可接收的参数类型不同:submit()方法可以接收Callable对象、Runnable对象或Runnable实现类的对象作为参数;而execute()方法只能接收Runnable对象或Runnable实现类的对象作为参数。

实例

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public class ScheduledThreadPoolExample {public static void main(String[] args) {// 创建ScheduledThreadPool,指定线程池中的线程数为3ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);// 定义一个Runnable任务Runnable task = new Runnable() {@Overridepublic void run() {System.out.println("Task executed at " + System.currentTimeMillis());}};// 使用scheduledExecutorService调度任务,在延迟1秒后开始执行任务,并且每隔3秒重复执行scheduledExecutorService.scheduleAtFixedRate(task, 1, 3, TimeUnit.SECONDS);// 主线程休眠10秒,以便观察任务的执行try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}// 关闭ScheduledThreadPoolscheduledExecutorService.shutdown();}
}

在这个示例中,我们首先创建了一个ScheduledThreadPool,指定线程池中的线程数为3。

然后,我们定义了一个Runnable任务,该任务将在执行时打印当前时间。

接下来,我们使用scheduledExecutorService.scheduleAtFixedRate()方法来调度任务。这个方法接受四个参数:任务、延迟时间、重复间隔和时间单位。在这个例子中,我们将任务延迟1秒后开始执行,并且每隔3秒重复执行一次。

最后,我们让主线程休眠10秒,以便观察任务的执行。然后,我们调用scheduledExecutorService.shutdown()方法来关闭ScheduledThreadPool。

 总结

线程池的主要优点如下:

  1. 重用线程:线程池可以重用已经创建的线程,避免了频繁地创建和销毁线程的开销。
  2. 控制并发数量:线程池可以限制并发线程的数量,防止过多的线程导致系统资源的浪费或者负载过重。
  3. 提高响应速度:线程池可以预先创建一组线程,当任务到达时可以立即执行,而不需要等待线程的创建过程,从而提高系统响应速度。
  4. 提供线程管理和监控功能:线程池可以提供一些管理和监控的方法,用于管理和监控线程的状态和运行情况。

使用线程池时需要注意以下几点:

  1. 线程池大小的选择:线程池的大小需要根据系统的负载和资源情况进行选择,太小会导致线程不足,任务无法及时处理,太大会导致资源浪费和负载过重。
  2. 线程池的关闭:在程序结束时需要正确地关闭线程池,释放资源,避免资源泄漏。
  3. 任务的提交方式:任务的提交可以采用不同的方式,如同步提交、异步提交等,需要根据实际需要进行选择。
  4. 错误处理机制:线程池需要有相应的错误处理机制,处理任务执行过程中的异常情况。

    

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

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

相关文章

sysbench安装(在线离线)

简介 sysbench是一个多线程基准测试工具,它支持硬件(CPU、内存、I/O)、数据库基准压测等2种测试手段,用于评估系统的基本性能。本篇文章主要介绍sysbench在线和离线2种安装方法,并将离线编译时发生的异常记录到FAQ&…

Filebeat进阶指南:核心架构与功能组件的深度剖析

🐇明明跟你说过:个人主页 🏅个人专栏:《洞察之眼:ELK监控与可视化》🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是ELK 2、FileBeat在ELK中的角色 二、Fil…

触摸屏是输入设备还是输出设备?

从功能上讲,触摸屏理应属于输入设备,之所以有很多用户会误会它是输出设备,是因为将其与“触摸显示屏”搞混了,以手机屏幕为例,它并不是单层屏幕,而是有多个不同功能和作用组成的集成屏,这类带有…

c++大作业 调整字幕的时间

作业及其需求 有时候人们能够下载一些感兴趣的视频但是发现并没有字幕,到字幕网站上查找到字幕文件,但是发现时间进度上不能完美配合,一个视频数据的例子来源于链接: BBC.巴塔哥尼亚:地球秘密乐园 https://www.aliyundrive.com/s/LmF2sgrQzMu/folder/612af030c6fa4bf4b7c…

HCIP的学习(24)

第七章,VLAN—虚拟局域网 ​ 通过在交换机上部署VLAN技术,将一个规模较大的广播域在逻辑上划分成若干个不同的、规模较小的广播域。 ​ IEEE 802.1Q标准----虚拟桥接局域网标准----Dot1Q标准 标签协议标识符:0x8011(代表数据帧是8…

前端 JS 经典:浏览器中 ESModule 的工作原理

前言&#xff1a;在开发中&#xff0c;我们经常写出如下代码。这就是 ES 模块化。那浏览器是如何运行的&#xff0c;它的运作机制到底是怎么样的呢。 在 index.html 导入 main.js <script src"./main.js" type"module"></script> 在 main.j…

广西教育杂志社与广西教育编辑部

【广西教育】期刊咨询电话&#xff1a;18366155179 咨询电话&#xff1a;18366155179编辑部----论文投稿---【广西教育】杂志编辑部--期刊发表---【广西教育】编辑期刊出刊--【广西教育】在线咨询---编辑QQ&#xff1a;1529962369 【广西教育】----在线投稿QQ&#xff1a;26480…

【文献阅读】移动边缘计算中基于CNN模型分割的计算适配和负载均衡研究_黄煜

论文原链接&#xff1a;移动边缘计算中基于CNN模型分割的计算适配和负载均衡研究 缩写词 MEC&#xff1a;移动边缘计算&#xff1b; CNN&#xff1a;卷积神经网络&#xff1b; QoE&#xff1a;体验质量&#xff1b; LB&#xff1a;负载均衡&#xff1b; ITM&#xff1a;反变换…

DM8启动报错:全局参数非法

问题描述 开发让把数据库启动下&#xff0c;启动后输入如下报错&#xff1a; 字面意思的报错就是参数非法&#xff0c;推测是有人改参数没改对&#xff0c;可是和开发沟通没人改参数。 --查看进程 [roottopnet31 ~]# ps -ef | grep dmserver dmdba 34732 1 1 5月27 …

K8s service 进阶

文章目录 K8s service 进阶Service 工作逻辑Service 具体实现Service 资源类型ClusterIPNodePortLoadBalancerExternalName Service 与 EndpointEndpoint 与 容器探针自定义Endpoint Service 相关字段sessionAffinityexternalTrafficPolicyinternalTrafficPolicypublishNotRead…

异构图上的连接预测二

异构图上的连接预测二 对整个大图进行transform处理获取批次子图定义GNN网络定义分类器&#xff1a;整合模型。开始训练&#xff1a; 对整个大图进行transform处理 详细描述过程都在代码中体现。 transform T.RandomLinkSplit(num_val0.1, # 10%的 边 作为验证集&#xff0c…

Python怎么实现动态的方法调用?比如Ruby就有元编程

在Python中&#xff0c;你可以使用getattr函数来实现动态的方法调用&#xff0c;这与Ruby中的元编程类似。getattr函数用于获取对象&#xff08;如模块、类、实例等&#xff09;的属性&#xff0c;如果属性是一个方法&#xff0c;那么你可以像调用普通方法一样调用它。 以下是一…

cfa三级大神复习经验分享系列(三)

怎么才能通过考试&#xff1f;   很简单----努力&#xff01; 第一&#xff1a;要熟   书看得再多&#xff0c;知识点掌握得再全面&#xff0c;最终是在考试中体现出来。光看书不行&#xff1b;只是看懂了不行&#xff1b;看懂了&#xff0c;记不住不行&#xff1b;记住了…

Chisel入门——在windows下vscode搭建|部署Scala2.13.3开发环境|用Chisel点亮FPGA小灯

文章目录 前言一、vscode搭建scala开发环境1.1 安装Scala官方插件Scala Syntax1.2 创建hello_world.scala文件1.3 确认java的版本(博主使用的是1.8)1.4 下载Scala Windows版本的二进制文件1.5 配置环境变量1.6 交互模式测试一下1.7 vscode运行scala 二、windows安装sbt2.1 下载…

全屏后 element-ui 组件不显示

文章目录 问题分析ElementUI 解决方案ElementPlus 解决方案 注意 问题 上篇我们说到如何 将 DIV 全屏展示 在使用将页面中指定的 DIV 全屏展示后&#xff0c;出现全屏后 element-ui 组件不显示&#xff0c;全屏后展示的提示信息是没有的&#xff0c;如下如所示&#xff1a; 全…

【linux自动化实践】linux shell 脚本 替换某文本

在Linux shell脚本中&#xff0c;可以使用sed命令来替换文本。以下是一个基本的例子&#xff0c;它将在文件example.txt中查找文本old_text并将其替换为new_text sed -i s/old_text/new_text/g example.txt解释&#xff1a; sed: 是stream editor的缩写&#xff0c;用于处理文…

Docker 入门版

目录 1. 关于Docker 2. Dockr run命令中常见参数解读 3. Docker常见命令 4. Docker 数据卷 5. Docker本地目录挂载 6. 自定义镜像 Dockerfile 语法 自定义镜像模板 Demo 7. Docker网络 1. 关于Docker 在docker里面下载东西&#xff0c;就是相当于绿色面安装板&#x…

Android ViewPager2 + FragmentStateAdapter 的使用以及问题

场景介绍&#xff1a;在Android业务功能开发的过程中&#xff0c;需要使用到嵌套ViewPage2实现页面切换&#xff0c;这种场景在我们的开发过程中并不少见&#xff0c;大致结构为一个activity包含一个viewPage2&#xff0c;这个viewPage2中存在一个fragment A&#xff0c;fragme…

视频智能分析平台LntonAIServer视频监控管理平台裸土检测算法的重要性与应用

随着科技的飞速发展&#xff0c;人工智能技术在各个领域的应用越来越广泛。其中&#xff0c;LntonAIServer裸土检测算法作为一种先进的技术手段&#xff0c;已经在农业、环境保护等领域取得了显著的成果。本文将探讨LntonAIServer裸土检测算法的重要性及其在实际应用中的优势。…

go语言中的一个优雅的冥等补偿算法 backoff - 业务逻辑重试示例

今天给大家介绍一个go语言里面的冥等补偿算法库 backoff&#xff0c; 他可以用来对我们需要冥等补偿的业务逻辑进行重试&#xff0c;我们可以设定一个最大间隔时间&#xff0c; 停止时间等重试规则&#xff0c;废话不多说直接三示例&#xff1a; 业务逻辑重试示例 exp : backo…