Java面试——线程池

1、类比介绍

  假如有一个工厂,工厂里面有10个工人,每个工人同时只能做一件任务。

  因此只要当10个工人中有工人是空闲的,来了任务就分配给空闲的工人做;

  当10个工人都有任务在做时,如果还来了任务,就把任务进行排队等待;

  如果说新任务数目增长的速度远远大于工人做任务的速度,那么此时工厂主管可能会想补救措施,比如重新招4个临时工人进来;

  然后就将任务也分配给这4个临时工人做;

  如果说着14个工人做任务的速度还是不够,此时工厂主管可能就要考虑不再接收新的任务或者抛弃前面的一些任务了。

  当这14个工人当中有人空闲时,而新任务增长的速度又比较缓慢,工厂主管可能就考虑辞掉4个临时工了,只保持原来的10个工人,毕竟请额外的工人是要花钱的。

 

  这个例子中的corePoolSize就是10,而maximumPoolSize就是14(10+4)。

  也就是说corePoolSize就是线程池大小,maximumPoolSize在我看来是线程池的一种补救措施,即任务量突然过大时的一种补救措施。

2、源码分析

在ThreadPoolExecutor类中,最核心的任务提交方法是execute()方法,虽然通过submit也可以提交任务,但是实际上submit方法里面最终调用的还是execute()方法,所以我们只需要研究execute()方法的实现原理即可:

public void execute(Runnable command) {if (command == null)throw new NullPointerException();if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {if (runState == RUNNING && workQueue.offer(command)) {if (runState != RUNNING || poolSize == 0)ensureQueuedTaskHandled(command);}else if (!addIfUnderMaximumPoolSize(command))reject(command); // is shutdown or saturated
    }
}

 

在addThread方法中,首先用提交的任务创建了一个Worker对象,然后调用线程工厂threadFactory创建了一个新的线程t,然后将线程t的引用赋值给了Worker对象的成员变量thread,接着通过workers.add(w)将Worker对象添加到工作集当中。

private Thread addThread(Runnable firstTask) {Worker w = new Worker(firstTask);Thread t = threadFactory.newThread(w);  //创建一个线程,执行任务   if (t != null) {w.thread = t;            //将创建的线程的引用赋值为w的成员变量       
        workers.add(w);int nt = ++poolSize;     //当前线程数加1       if (nt > largestPoolSize)largestPoolSize = nt;}return t;
}

 

下面总结一下:

  1)首先,要清楚corePoolSize和maximumPoolSize的含义;

  2)其次,要知道Worker是用来起到什么作用的;

  3)要知道任务提交给线程池之后的处理策略,这里总结一下主要有4点:

  • 如果当前线程池中的线程数目小于corePoolSize,则每来一个任务,就会创建一个线程去执行这个任务;
  • 如果当前线程池中的线程数目>=corePoolSize,则每来一个任务,会尝试将其添加到任务缓存队列当中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务;
  • 如果当前线程池中的线程数目达到maximumPoolSize,则会采取任务拒绝策略进行处理;
  • 如果线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止,直至线程池中的线程数目不大于corePoolSize;如果允许为核心池中的线程设置存活时间,那么核心池中的线程空闲时间超过keepAliveTime,线程也会被终止。

3.线程池中的线程初始化

  默认情况下,创建线程池之后,线程池中是没有线程的,需要提交任务之后才会创建线程。

  在实际中如果需要线程池创建之后立即创建线程,可以通过以下两个方法办到:

  • prestartCoreThread():初始化一个核心线程;
  • prestartAllCoreThreads():初始化所有核心线程

 

4.任务缓存队列及排队策略

  在前面我们多次提到了任务缓存队列,即workQueue,它用来存放等待执行的任务。

  workQueue的类型为BlockingQueue<Runnable>,通常可以取下面三种类型:

  1)ArrayBlockingQueue:基于数组的先进先出队列,此队列创建时必须指定大小;

  2)LinkedBlockingQueue:基于链表的先进先出队列,如果创建时没有指定此队列大小,则默认为Integer.MAX_VALUE;

  3)synchronousQueue:这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。

 

5.任务拒绝策略

当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务 

6.线程池的关闭

  ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow(),其中:

  • shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
  • shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务

7.线程池容量的动态调整

  ThreadPoolExecutor提供了动态调整线程池容量大小的方法:setCorePoolSize()和setMaximumPoolSize(),

  • setCorePoolSize:设置核心池大小
  • setMaximumPoolSize:设置线程池最大能创建的线程数目大小

  当上述参数从小变大时,ThreadPoolExecutor进行线程赋值,还可能立即创建新的线程来执行任务。

 

转载于:https://www.cnblogs.com/chappell/p/9084496.html

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

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

相关文章

C#关键字的使用

params object[] 用于函数多参数的定义public static void Write(string format, params object[] arg);explicit 关键字用于声明必须使用强制转换来调用的用户定义的类型转换运算符。 例如&#xff0c;在下面的示例中&#xff0c;此运算符将名为 Fahrenheit 的类转换为名为 Ce…

maven 中 pom.xml 配置文件标签说明,dependencyManagement和dependencies区别

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 参考&#xff1a;http://zhaoshijie.iteye.com/blog/2094478http://blog.csdn.net/cpf2016/article/details/45674377 还有一篇转载文章…

学成在线--17.我的课程

文章目录一.需求分析二.API接口三.PageHelper1.PageHelper介绍2.添加依赖3.配置pageHelper四.Dao1.mapper 接口2.mapper.xml映射文件3.测试Dao五.Service六.Controller七.前端1.创建course_list.vue2.路由3.定义API方法4.前端视图course_list.vue详解1&#xff09;API调用--在视…

码是数据系统中的基本概念。所谓码就是能唯一标识实体的属性或属性集合&#xff0c;他是整个实体集的性质&#xff0c;而不是单个实体的性质。 主属性与非主属性 包含在任何一个候选码中的属性 &#xff0c;称为主属性&#xff08;Prime attribute&#xff09;。 不包含在任何…

关于C编程的一点感受

刚毕业的时候用了两个多月的C语言编程&#xff0c;总的来说对它还是很有感受的&#xff0c;C是一个过程式语言&#xff0c;没有像C,Java等OOP语言这样那样的一系列的规则和限制&#xff1b;它比较灵活&#xff0c;简洁&#xff0c;高效&#xff1b;这些是给我的印象最深的。这是…

如何打造高效的多任务、高并发的网络服务器系统?

同一个功能的软件&#xff0c;不同的团队&#xff0c;不同工程师去实现&#xff0c;肯定是千差万别&#xff0c;甚至从根本上完全不同。所以软件开发在未来很长时间内仍然是一项工匠的手工劳动&#xff0c;尤其像多任务&#xff0c;高并发&#xff0c;偏底层这种对实现技巧比较…

BZOJ.2780.[SPOJ8093]Sevenk Love Oimaster(广义后缀自动机)

题目链接 \(Description\) 给定n个模式串&#xff0c;多次询问一个串在多少个模式串中出现过。(字符集为26个小写字母) \(Solution\) 对每个询问串进行匹配最终会达到一个节点&#xff0c;我们需要得到这个节点所代表的子串出现在多少个模式串中。 建立广义后缀自动机。每次插入…

BigDecimal 加减乘除运算

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 java.math.BigDecimal。BigDecimal一共有4个够造方法&#xff0c;让我先来看看其中的两种用法&#xff1a; 第一种&#xff1a;BigDeci…

主码 超码 候选码

码是数据系统中的基本概念。所谓码就是能唯一标识实体的属性&#xff0c;他是整个实体集的性质&#xff0c;而不是单个实体的性质。它包括超码&#xff0c;候选码&#xff0c;主码。   超码是一个或多个属性的集合&#xff0c;这些属性可以让我们在一个实体集中唯一地标识一…

学成在线--18.新增课程(课程分类查询)

文章目录一.需求分析二.课程分类查询介绍三.数据结构四.数据格式五.数据模型六.Api接口七.服务器端1.Dao1&#xff09;定义mapper2&#xff09;定义mapper映射文件2.Service3.Controller八.接口测试一.需求分析 用户操作流程如下&#xff1a; 1、用户进入“我的课程”页面&…

给程序员们的工资报价提醒

在薪水上讨价还价的方式有很多种&#xff0c;我要说的这一点也许并不是最好的。然而&#xff0c;如果使用的得当&#xff0c;会收到很好的效果。如果你正在跟一家公司接触(没有经过职业中介)&#xff0c;而且事情看来很顺利&#xff0c;进度很快&#xff0c;你要保持这种面试的…

POI 方式-excle 表格导出实现-java-poi

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 效果&#xff1a; jsp 页面 用的Bootstrap &#xff1a; <li class"dropdown"> <a href"javascript:void(0)…

02-css的选择器

css的选择器&#xff1a;1.基本选择器 2.高级选择器 基本选择器包含&#xff1a; 1.标签选择器标签选择器可以选中所有的标签元素&#xff0c;比如div&#xff0c;ul&#xff0c;li &#xff0c;p等等&#xff0c;不管标签藏的多深&#xff0c;都能选中&#xff0c;选中的是所有…

iphoneX样式兼容

// 1.viewport meta 标签增加属性viewport-fitcover // 2.body元素增加样式 body { padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); } // 3.如有fixed底部的元素&#xff0c;也增加上面样式 xxx { padding-bottom: constant…

学成在线--19.新增课程(数据字典)

文章目录一.介绍二.数据模型三.数据模型类四.字典查询API接口五.服务器端1.Dao2.Service3.Controller一.介绍 在新增课程界面需要选择课程等级、课程状态等&#xff0c;这些信息统一采用数据字典管理的方式。 本项目对一些业务的分类配置信息&#xff0c;比如&#xff1a;课程…

范式简介

范式是符合某一种级别的关系模式的集合。关系数据库中的关系必须满足一定的要求。满足不同程度要求的为不同范式。范式的种类&#xff1a; 第一范式(1NF) 第二范式(2NF) 第三范式(3NF) BC范式(BCNF) 第四范式(4NF) 第五范式(5NF) 一个低一级范式的关系模式&#xff0c;通过模…

程序员的进化

对于很多同学来说&#xff0c;他们对程序员的职业生涯非常关注。而这本质上是一个进化的过程。我们将如何进化&#xff1f;在每个进化阶段我们应该如何提高自己&#xff1f;下面的文章根据我自己的切身经历和阅读过的书&#xff0c;为程序员每个阶段的进化提供了不同的学习思路…

【树形dp】vijos1144小胖守皇宫

细节很精妙 描述 huyichen世子事件后&#xff0c;xuzhenyi成了皇上特聘的御前一品侍卫。 皇宫以午门为起点&#xff0c;直到后宫嫔妃们的寝宫&#xff0c;呈一棵树的形状&#xff1b;某些宫殿间可以互相望见。大内保卫森严&#xff0c;三步一岗&#xff0c;五步一哨&#xff0c…

手机号码归属地及运营商查询

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL;public class NewMobile {public stati…

redhat6.5手动配置网络

2、手动设置ip地址如果虚拟机不能自动获取IP&#xff0c;只能手动配置&#xff0c;配置方法如下&#xff1a;输入命令#vi /etc/sysconfig/network-scripts/ifcfg-eth0 [编辑网卡的配置文件]输入上述命令后回车&#xff0c;打开配置文件&#xff0c;使用方向键移动光标到最后一行…