首页 > 编程语言 >Java线程池详解

Java线程池详解

时间:2024-08-20 17:41:03浏览次数:7  
标签:ExecutorService Java Callable 任务 详解 线程 执行 ThreadPoolExecutor

Java线程池详解

线程池解释

线程池采用了池化思想,能够有效的管理线程的生命周期,减少了每次获取资源的消耗,提高了资源的利用率。类似池化实现还有数据库连接池、HTTP连接池等

好处

  • 减少了线程创建和销毁的开销
  • 提高了响应速度
  • 使得线程更加方便管理

常见使用场景

  • 量大处理时间较短的任务:有效利用线程池减少线程创建销毁的消耗
  • 需要限制线程数量时:线程越多对资源的消耗越大,线程池可以设置最大线程数进行限制
  • 异步执行一批不需要立刻反馈结果的任务:异步执行任务,减少系统响应时间

线程池的引入:Executor框架

Executor框架为Java 5 引入,将传统线程的操控方法进行优化升级,使其针对不同 场景更加的灵活、管理更加的方便,其核心jar包为java.util.concurrent,简称JUC。此外,很重要的一点,该框架还避免了 this逃逸问题。

this逃逸:指在构造函数返回之前,其他线程持有了该对象的引用,此时引用该对象调用其方法时,可能会出现不好排查的异常。

Executor框架主要包括三个部分

  • 任务:Runnabale/Callable,可以被 ThreadPoolExecutorScheduledThreadPoolExecutor(继承ThreadPoolExecutor) 执行

  • 执行:通过实现Executor接口的子接口ExecutorService去构造相对来说比较完整的线程池执行系统

  • 返回值:线程池的优势之一,通过实现Futrure接口的FutureTask 类将异步执行的结果获取到

  • 主线程创建 Runnable 或者 Callable 的任务对象,然后把 实现的 Runnbale 或者 Callable 交给 ExecutorService 执行:ExecutorService.execute(Runnable command) 或者 把 Runnable对象或者 Callable 对象提交给 ExecutorService 执行(ExecutorService.submit(Runnable command)

  • 如果执行 ExecutorService.submit()ExecutorService 返回一个实现了 Future 接口的对象(submit() 会返回一个 FuturesTask对象,FutureTask 实现了 Runnable,可以创建FutureTask,然后直接交给 ExecutorService执行;execute 则会把异常打印出来)

  • 最后,主线程执行 FuturesTask.get() 方法等待任务执行完成。也可以通过 FutureTask.cancel(boolean mayInterruptIfRunning) 来取消此任务执行。

ThreadPoolExecutor为例,ThreadPoolExecutor继承了AbstractExecutorService(抽象函数)的submit方法,并且实现了AbstractExecutorService来自Executor接口的execute方法,因此在调用线程池的submit方法时就会通过ThreadPoolExecutorexecute将任务(Runnabale/Callable为核心的RunnableFuture对象)加到工作队列中(addWorker方法实现),返回值则通过RunnableFuture对象的形式返回。

简单来说就是主线程将Runnabale/Callable对象通过submit方法提交给线程池,线程池通过内部调度按照不同的策略执行多线程任务,然后通过返回的Futrure对象的get方法取出执行结果。

ThreadPoolExecutor 类

线程池实现类 ThreadPoolExecutorExecutor 框架最核心的类

主线程提交任务后

  • 第一步,判断核心线程池线程数是否已满,若未满则创建线程,若已满则进入第二步
  • 第二步,判断等待队列是否已满,若未满则加入队列,若已满则进入第三步
  • 第三步,判断最大线程数是否已满,若未满则创建线程,若已满则根据设定的拒绝策略处理
参数介绍:
  • corePoolSize:核心线程数,能第一时间处理的线程数
  • maximumPoolSize:最大线程数,当核心线程池以及队列都满了的时候,线程池就会扩充到最大线程数
  • workQueue: 当核心线程池已满时,队列可以用来暂存后边进来的任务
  • keepAliveTime:线程数量大于核心线程数量时,线程闲置时间超过此值的线程会被回收掉,直至缩到核心线程数
  • unitkeepAliveTime 参数的时间单位
  • threadFactory:线程工厂,executor 创建线程时用到
  • handler:拒绝策略线程池已达到最大线程数,此时队列也满了,再有任务进来就会触发拒绝策略
拒绝策略:
  • AbortPolicy:拒绝任务并抛异常RejectedExecutionException
  • CallerRunsPolicy:直接在调用线程中执行任务,影响性能
  • DiscardPolicy:拒绝任务,不报异常,不做任何处理
  • DiscradOldestPolicy:拒绝掉最早的任务,执行最新的

线程池相关的内容有很多,该文章重在介绍,若要深究其中的某个元素,可以通过参考源码的方式,这样可以最直观的看到内部组成以及各个元素之间如何合作解决线程池的实现问题。

标签:ExecutorService,Java,Callable,任务,详解,线程,执行,ThreadPoolExecutor
From: https://www.cnblogs.com/zyyjgsj/p/18369916

相关文章

  • JavaScript基础(2)
    记录一些js基础语法的总结第二篇——流程控制<!DOCTYPEhtml><htmllang="zh-CN"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>jsStu......
  • 免费国产 Java 反编译工具 jdecode.net
    免费国产Java反编译工具jdecode.netjdecode于2024-04-2512:04:37发布阅读量1.1k收藏20点赞数27文章标签:java开发语言版权网站地址:www.jdecode.net推荐理由:功能强大、成功率高、错误少、安全、免费、国产1、功能强大主流版本支持:支持Java5~11主流版本,经过大规......
  • Effective-Java-Chapter9-通用程序设计
    https://github.com/clxering/Effective-Java-3rd-edition-Chinese-English-bilingual/blob/dev/Chapter-9/Chapter-9-Introduction.md准则一将局部变量的作用域最小化不要在变量使用之前就申明,在需要使用的时候进行申明。当然这条准则不是那么绝对,大部分时候遵守就好。......
  • Java中stream流的filter机制理解
    一开始我并不理解,为什么filter接受一个实现了Predicate接口的对象后,就能通过重写的test方法来筛选元素,这个将筛选后的元素放到新的流中,我并不知道如何实现的。后来我发现ReferencePipeline抽象类中重写了filter方法,并且Collection中的stream方法返回的是StreamSupport.stream方法......
  • java_数组
    1.数组概念:指的是一种容器,可以同来存储同种数据类型的多个值。但是数组容器在存储数据的时候,需要结合隐式转换考虑。比如:定义了一个int类型的数组。那么boolean。double类型的数据是不能存到这个数组中的,但是byte类型,short类型,int类型的数据是可以存到这个数组里面的。建议......
  • 【原创】java+swing+mysql网吧管理系统设计与实现
    个人主页:程序员杨工个人简介:从事软件开发多年,前后端均有涉猎,具有丰富的开发经验博客内容:全栈开发,分享Java、Python、Php、小程序、前后端、数据库经验和实战文末有本人名片,希望和大家一起共同努力,一起进步,顶峰相见。开发背景:随着互联网技术的飞速发展和普及,网络已成为人......
  • JavaScript 中的 闭包
    闭包在JavaScript中,你可以在其他函数内部声明并返回函数。内部函数可以访问在其上方声明的任何变量。functioncreateAdder(a){returnfunctionadd(b){constsum=a+b;returnsum;}}constaddTo2=createAdder(2);addTo2(5)//7addTo2(0)//2......
  • C# Deflate压缩字节数组(和java压缩结果一样)利用zlib.net对文件进行压缩
    今天在对接一个三方接口时,需要传一个附件数据,附件需要使用Deflate压缩算法压缩后的文件二进制流,再进行base64编码后的字符串。刚开始使用的官方自带的System.IO.Compression.DeflateStream方式,结果不管怎么改变CompressionLevel级别,压缩结果始终和java的压缩结果不一致,结果不一致......
  • [Java基础]int的表示范围
    在java基础类型中,int类型占四个字节,而每个字节在内存中占8位(8byte),所以可以使用共4X8=32个位数来存储该类型,也就是四个八位的二进制数,所以有了以下说法在计算机中,它的二级制表示为四个长度为8的二进制数,00000000000000000000000000000000,不了解的同学可以补一下原码,反码和补......
  • java+vue计算机毕设健身信息管理系统【源码+开题+论文】
    本系统(程序+源码)带文档lw万字以上文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着现代生活节奏的加快,人们对健康生活的追求日益增强,健身已成为许多人日常生活不可或缺的一部分。传统的健身管理方式往往存在效率低下、信息不透明......