当前位置: 首页 > news >正文

Java_多线程:线程池

1、线程池优点:

  • 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
  • 提高响应速度:当任务到达时,任务可以不需要等到线程创建就能立即执行。
  • 提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

2、常用的线程池

  • newSingleThreadExecutor:创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
  • newFixedThreadPool:创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
    FixedThreadPool是一个典型且优秀的线程池,它具有线程池提高程序效率和节省创建线程时所耗的开销的优点。但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。
  • newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    特点
    • 工作线程的创建数量几乎没有限制(其实也有限制的,数目为Interger. MAX_VALUE), 这样可灵活的往线程池中添加线程。
    • 如果长时间没有往线程池中提交任务,即如果工作线程空闲了指定的时间(默认为1分钟),则该工作线程将自动终止。终止后,如果你又提交了新的任务,则线程池重新创建一个工作线程。
    • 在使用CachedThreadPool时,一定要注意控制任务的数量,否则,由于大量线程同时运行,很有会造成系统OOM。
  • newScheduledThreadPool:创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。

3、线程池七个核心参数

  • corePoolSize : 核心线程大小。线程池一直运行,核心线程就不会停止。
  • maximumPoolSize :线程池最大线程数量。非核心线程数量=maximumPoolSize-corePoolSize
  • keepAliveTime :非核心线程的心跳时间。如果非核心线程在keepAliveTime内没有运行任务,非
    核心线程会消亡。
  • workQueue :阻塞任务队列。ArrayBlockingQueue,LinkedBlockingQueue等,用来存放线程任
    务。
  • defaultHandler :饱和策略。ThreadPoolExecutor类中一共有4种饱和策略。通过实现RejectedExecutionHandler接口。
    • AbortPolicy : 线程任务丢弃报错。默认饱和策略。
    • DiscardPolicy : 线程任务直接丢弃不报错。
    • DiscardOldestPolicy : 将workQueue队首任务丢弃,将最新线程任务重新加入队列执行。
    • CallerRunsPolicy :线程池之外的线程直接调用run方法执行。
  • ThreadFactory :线程工厂。新建线程工厂。

4、线程池的执行流程

在这里插入图片描述

  1. 线程池执行execute/submit方法向线程池添加任务,当任务小于核心线程数corePoolSize,线程池中可以创建新的线程,即使线程池中仍有空闲线程。
  2. 当任务大于核心线程数corePoolSize,就向阻塞队列workQueue添加任务。
  3. 阻塞队列workQueue满了,并且最大线程池大小maximumPoolSize > 核心线程数corePoolSize时,新提交任务会创建新的线程执行任务。
  4. 当提交任务数超过最大线程池大小maximumPoolSize,就会执行饱和策略
  5. 当线程池中超过核心线程数corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程。
  6. 当设置allowCoreThreadTimeOut(true)时,线程池中核心线程数corePoolSize线程空闲时间达到keepAliveTime也将关闭

5、execute()方法和submit()方法的区别

  • execute()方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功
    与否。
  • submit()方法用于提交需要返回值的任务。线程池会返回一个future类型的对象,通过这个future对象可以判断任务是否执行成功,并且可以通过future的get()方法来获取返回值,get()方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit) 方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。

6、扩展

线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

相关文章:

  • Spring Boot与Apache Kafka的深度集成
  • 如何利用React和Python构建强大的网络爬虫应用
  • leetcode-20-回溯-切割、子集
  • 5G赋能安防视频监控:EasyCVR视频汇聚融合创新技术,共筑多场景安全防线
  • 学习springAOP
  • 重写父类方法、创建单例对象 题目
  • 发布一个Yii2扩展把debug信息存储到MongoDB中
  • el-scrollbar组件使用踩坑记录
  • 求推荐几款http可视化调试工具?
  • HNU_ACM:10415分硬币(动态规划)
  • 解析Kotlin中的委托(包括类委托,属性委托)【笔记摘要】
  • 国家海岸线变化评估:新英格兰和中大西洋沿岸海岸线的历史变化
  • Handling `nil` Values in `NSDictionary` in Objective-C
  • 煤矿安全大模型:微调internlm2模型实现针对煤矿事故和煤矿安全知识的智能问答
  • 基于C#在WPF中使用斑马打印机进行打印
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • Consul Config 使用Git做版本控制的实现
  • E-HPC支持多队列管理和自动伸缩
  • HomeBrew常规使用教程
  • JavaScript设计模式之工厂模式
  • Making An Indicator With Pure CSS
  • PHP那些事儿
  • python docx文档转html页面
  • Quartz初级教程
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • unity如何实现一个固定宽度的orthagraphic相机
  • vue.js框架原理浅析
  • 分布式任务队列Celery
  • 理清楚Vue的结构
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 删除表内多余的重复数据
  • 实现菜单下拉伸展折叠效果demo
  • 一些css基础学习笔记
  • 用Visual Studio开发以太坊智能合约
  • 运行时添加log4j2的appender
  • 阿里云服务器如何修改远程端口?
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • #etcd#安装时出错
  • #数据结构 笔记三
  • #我与Java虚拟机的故事#连载09:面试大厂逃不过的JVM
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (pytorch进阶之路)扩散概率模型
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (十六)串口UART
  • (一)Thymeleaf用法——Thymeleaf简介
  • (一)WLAN定义和基本架构转
  • (原創) 物件導向與老子思想 (OO)
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • **PHP二维数组遍历时同时赋值
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .netcore 如何获取系统中所有session_如何把百度推广中获取的线索(基木鱼,电话,百度商桥等)同步到企业微信或者企业CRM等企业营销系统中...
  • .net通用权限框架B/S (三)--MODEL层(2)