服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|JavaScript|易语言|

服务器之家 - 编程语言 - JAVA教程 - 基于线程池的工作原理与源码解读

基于线程池的工作原理与源码解读

2021-03-13 14:19metoy JAVA教程

下面小编就为大家分享一篇基于线程池的工作原理与源码解读,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

随着cpu核数越来越多,不可避免的利用多线程技术以充分利用其计算能力。所以,多线程技术是服务端开发人员必须掌握的技术。

线程的创建和销毁,都涉及到系统调用,比较消耗系统资源,所以就引入了线程池技术,避免频繁的线程创建和销毁。

在java用有一个executors工具类,可以为我们创建一个线程池,其本质就是new了一个threadpoolexecutor对象。线程池几乎也是面试必考问题。本节结合源代码,说说threadexecutor的工作原理

一、线程池创建

先看一下threadpoolexecutor参数最全的构造方法:

基于线程池的工作原理与源码解读

①corepoolsize:线程池的核心线程数,说白了就是,即便是线程池里没有任何任务,也会有corepoolsize个线程在候着等任务。

②maximumpoolsize:最大线程数,不管你提交多少任务,线程池里最多工作线程数就是maximumpoolsize。

③keepalivetime:线程的存活时间。当线程池里的线程数大于corepoolsize时,如果等了keepalivetime时长还没有任务可执行,则线程退出。

⑤unit:这个用来指定keepalivetime的单位,比如秒:timeunit.seconds。

⑥workqueue:一个阻塞队列,提交的任务将会被放到这个队列里。

⑦threadfactory:线程工厂,用来创建线程,主要是为了给线程起名字,默认工厂的线程名字:pool-1-thread-3。

⑧handler:拒绝策略,当线程池里线程被耗尽,且队列也满了的时候会调用。

以上就是创建线程池时用到的参数,面试中经常会有面试官问道这个问题。

二、线程池执行流程

这里用一个图来说明线程池的执行流程

基于线程池的工作原理与源码解读

任务被提交到线程池,会先判断当前线程数量是否小于corepoolsize,如果小于则创建线程来执行提交的任务,否则将任务放入workqueue队列,如果workqueue满了,则判断当前线程数量是否小于maximumpoolsize,如果小于则创建线程执行任务,否则就会调用handler,以表示线程池拒绝接收任务。

这里以jdk1.8.0_111的源代码为例,看一下具体实现。

1、先看一下线程池的executor方法

基于线程池的工作原理与源码解读

①:判断当前活跃线程数是否小于corepoolsize,如果小于,则调用addworker创建线程执行任务

②:如果不小于corepoolsize,则将任务添加到workqueue队列。

③:如果放入workqueue失败,则创建线程执行任务,如果这时创建线程失败(当前线程数不小于maximumpoolsize时),就会调用reject(内部调用handler)拒绝接受任务。

2、再看下addworker的方法实现

基于线程池的工作原理与源码解读

这块代码是在创建非核心线程时,即core等于false。判断当前线程数是否大于等于maximumpoolsize,如果大于等于则返回false,即上边说到的③中创建线程失败的情况。

addworker方法的下半部分:

基于线程池的工作原理与源码解读

①创建worker对象,同时也会实例化一个thread对象。

②启动启动这个线程

3、再到worker里看看其实现

基于线程池的工作原理与源码解读

可以看到在创建worker时会调用threadfactory来创建一个线程。上边的②中启动一个线程就会触发worker的run方法被线程调用。

4、接下来咱们看看runworker方法的逻辑

基于线程池的工作原理与源码解读

线程调用runwoker,会while循环调用gettask方法从workerqueue里读取任务,然后执行任务。只要gettask方法不返回null,此线程就不会退出。

5、最后在看看gettask方法实现

基于线程池的工作原理与源码解读

①咱们先不管allowcorethreadtimeout,这个变量默认值是false。wc>corepoolsize则是判断当前线程数是否大于corepoolsize。

②如果当前线程数大于corepoolsize,则会调用workqueue的poll方法获取任务,超时时间是keepalivetime。如果超过keepalivetime时长,poll返回了null,上边提到的while循序就会退出,线程也就执行完了。

如果当前线程数小于corepoolsize,则会调用workqueue的take方法阻塞在当前。

以上这篇基于线程池的工作原理与源码解读就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。

原文链接:https://www.cnblogs.com/qingquanzi/p/8146638.html

延伸 · 阅读

精彩推荐
  • JAVA教程Javabean和map相互转化方法代码示例

    Javabean和map相互转化方法代码示例

    这篇文章主要介绍了Javabean和map相互转化方法示例,介绍了其通用方法代码,需要的朋友可以参考下。...

    chenxuejiakaren11252021-01-01
  • JAVA教程spring mvc常用注解_动力节点Java学院整理

    spring mvc常用注解_动力节点Java学院整理

    这篇文章主要介绍了spring mvc常用注解,详细的介绍了@RequestMapping, @RequestParam, @ModelAttribute等等这样类似的注解,有兴趣的可以了解一下...

    aijuans4802020-12-23
  • JAVA教程Java使用线程池的优势有哪些

    Java使用线程池的优势有哪些

    这篇文章主要介绍了Java使用线程池的优势有哪些,帮助大家更好的理解和掌握java池化技术,感兴趣的朋友可以了解下...

    崔笑颜4252020-09-09
  • JAVA教程详解JavaWeb中的 Listener

    详解JavaWeb中的 Listener

    JavaWeb里面的listener是通过观察者设计模式进行实现的。下面通过本文给大家详细介绍javaweb中的listener,感兴趣的朋友一起看看吧 ...

    南唐三少2952020-06-18
  • JAVA教程Java实现洗牌发牌的方法

    Java实现洗牌发牌的方法

    这篇文章主要介绍了Java实现洗牌发牌的方法,涉及java针对数组的遍历与排序操作相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下 ...

    罪恶的花生3682019-12-29
  • JAVA教程java中简单的截取分割字符串实例

    java中简单的截取分割字符串实例

    下面小编就为大家带来一篇java中简单的截取分割字符串实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    Java之家4282020-08-21
  • JAVA教程Java Eclipse进行断点调试的方法

    Java Eclipse进行断点调试的方法

    本篇文章主要介绍了Java Eclipse进行断点调试的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    邴越9982021-02-18
  • JAVA教程详解springboot整合mongodb

    详解springboot整合mongodb

    本篇文章主要介绍了详解springboot整合mongodb,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    方志朋3182020-09-24