当前位置:首页 > 科技  > 软件

面试官:听说你很懂线程池?

来源: 责编: 时间:2024-04-02 17:17:23 237观看
导读什么是线程池就是一种池化技术,类似的还有jdbc连接池,对象池。所谓线程池,就是提前创建一堆线程,放到内存(池子)中,需要的时候取一个出来用。如上图,最顶层的接口就是Executor,实现ExecutorService接口的类,就是对应的线程池类

什么是线程池

就是一种池化技术,类似的还有jdbc连接池,对象池。所谓线程池,就是提前创建一堆线程,放到内存(池子)中,需要的时候取一个出来用。m1U28资讯网——每日最新资讯28at.com

m1U28资讯网——每日最新资讯28at.com

如上图,最顶层的接口就是Executor,实现ExecutorService接口的类,就是对应的线程池类。m1U28资讯网——每日最新资讯28at.com

如何创建线程池

用Executors工具类,可以很方便地创建各种线程池。(但是实际开发我们不推荐,阿里巴巴的开发手册严令禁止使用Executors,应该用ThreadPoolExecutor)Executors 类可以创建多种类型的线程池,每种线程池都有不同的特点和适用场景。m1U28资讯网——每日最新资讯28at.com

(1) FixedThreadPool(固定大小线程池):m1U28资讯网——每日最新资讯28at.com

  • 使用 Executors.newFixedThreadPool(int nThreads) 方法创建。
  • 具有固定大小的线程池,即线程数量固定不变。
  • 适用于需要控制线程数量的场景,例如服务器端处理请求。

(2) CachedThreadPool(缓存线程池):m1U28资讯网——每日最新资讯28at.com

  • 使用 Executors.newCachedThreadPool() 方法创建。
  • 具有自动调整线程数量的线程池,根据需要创建新线程,空闲线程会被回收。
  • 适用于执行大量短期异步任务的场景,例如异步IO操作。

(3) SingleThreadPool(单线程线程池):m1U28资讯网——每日最新资讯28at.com

  • 使用 Executors.newSingleThreadExecutor() 方法创建。
  • 只有一个工作线程的线程池,所有任务按顺序执行。
  • 适用于需要保证顺序执行的任务场景,例如日志处理。

(4) ScheduledThreadPool(定时任务线程池):m1U28资讯网——每日最新资讯28at.com

  • 使用 Executors.newScheduledThreadPool(int corePoolSize) 方法创建。
  • 具有定时执行任务的功能,可以按固定的频率执行任务。
  • 适用于需要定时执行任务的场景,例如定时任务调度。

(5) WorkStealingPool(工作窃取线程池):m1U28资讯网——每日最新资讯28at.com

  • 使用 Executors.newWorkStealingPool(int parallelism) 方法创建。
  • 基于ForkJoinPool实现的线程池,每个线程都有自己的任务队列,可以窃取其他线程的任务来执行。
  • 适用于需要处理大量并行任务的场景,例如并行计算任务。

为什么不推荐用Executors创建?m1U28资讯网——每日最新资讯28at.com

m1U28资讯网——每日最新资讯28at.com

线程池底层原理

我们以ThreadPoolExecutor为例,它是ExecutorService的一种实现。m1U28资讯网——每日最新资讯28at.com

m1U28资讯网——每日最新资讯28at.com

一般我们根据一个类的构造器,可以看出里面的大致思路:m1U28资讯网——每日最新资讯28at.com

public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue,                              ThreadFactory threadFactory,                              RejectedExecutionHandler handler) {        if (corePoolSize < 0 ||            maximumPoolSize <= 0 ||            maximumPoolSize < corePoolSize ||            keepAliveTime < 0)            throw new IllegalArgumentException();        if (workQueue == null || threadFactory == null || handler == null)            throw new NullPointerException();        this.corePoolSize = corePoolSize;        this.maximumPoolSize = maximumPoolSize;        this.workQueue = workQueue;        this.keepAliveTime = unit.toNanos(keepAliveTime);        this.threadFactory = threadFactory;        this.handler = handler;    }

参数很多,但是我们每一个都必须要记住。 这个 ThreadPoolExecutor 的构造函数接受以下参数:一个线程池就好比一家公司,甲方员工干不完需求的时候,就要招一些外包人员驻场开发,如果活干完了,就让外包撤场,只留下自己的员工。m1U28资讯网——每日最新资讯28at.com

  • corePoolSize(核心线程数):线程池中保持活跃的线程数量,即使它们处于空闲状态。当提交任务时,线程池会尝试保持至少这么多数量的线程处于活跃状态。 就是公司正式员工的数量。
  • maximumPoolSize(最大线程数):线程池中允许的最大线程数量。当任务队列已满且核心线程都处于活跃状态时,线程池会创建新的线程,直到达到这个最大线程数。 就是公司甲方员工+外包员工的总数,不能超过这个数量。
  • keepAliveTime(线程空闲时间):非核心线程在空闲状态下的最长存活时间。超过这个时间,多余的非核心线程将被终止,直到线程数量不超过核心线程数。 如果外包员工长时间没需求,就通知乙方撤人,裁掉这个非核心人员。当然,甲方爸爸是不会裁的。
  • unit(时间单位):用于指定 keepAliveTime 参数的时间单位,通常是秒、毫秒、微秒等。
  • workQueue(工作队列):用于保存等待执行的任务的阻塞队列。当所有线程都处于忙碌状态时,新提交的任务会被放入这个队列中等待执行。 当需求多到加上外包员工都做不完了,就只能往后排期了。
  • threadFactory(线程工厂):用于创建新线程的工厂。每个新创建的线程都是通过这个工厂创建的。** 就是定义员工的属性,即工牌,这个员工属于哪个公司的。**
  • handler(拒绝策略):当任务无法被执行时(通常是由于线程池已关闭或者任务队列已满),用于处理被拒绝的任务的策略。常见的拒绝策略包括抛出异常、丢弃任务或者在调用者线程中执行任务。 默认是不处理。

这些参数可以用于配置 ThreadPoolExecutor 对象,以满足不同的线程管理需求。m1U28资讯网——每日最新资讯28at.com

线程池本质就是一个HashSet,所以是无序的。有新的任务提交进来,如果池子还有线程,就直接拿去处理,池子满了就放入阻塞队列,等待有线程空闲。m1U28资讯网——每日最新资讯28at.com

线程数怎么设置比较合理?

这个是没有银弹的,我们一般认为CPU密集型的应用,设置为CPU核数N+1。所谓CPU密集型,就是这个程序计算量比较多,还比较频繁,计算时间长,也就是所谓的比较吃配置,比如是一个专门做算法的服务(组托,配载运算之类的)。 m1U28资讯网——每日最新资讯28at.com

对于IO密集型的应用,设置为2N+1,什么是IO密集型的应用呢,就是提供数据服务比较多,吞吐量比较大,等待时间长的应用,大部分业务系统都属于此类。m1U28资讯网——每日最新资讯28at.com

除此之外,线程数还跟jvm,机器cpu是否可以超线程(云服务器一般没法超线程),我们看到的cpu核数一般不是真实的,所以我们推荐先根据常规设置一个线程数量,上线后根据具体情况再调整就行了。m1U28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-80831-0.html面试官:听说你很懂线程池?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 千人规模敏捷迭代实践分享,你学会了吗?

下一篇: JSDoc:一个可选的 TypeScript 替代品

标签:
  • 热门焦点
  • 女孩租房开2小时空调用完100元电费引热议:5级能耗惹不起 月薪过万电费也交不起

    近日,江苏苏州一女孩租房当天充值了100元电费,开着空调不到2小时发现电费已用完。对于为什么这个快,房东表示,电表坏了这种情况很多,之前也遇到过,给租客换
  • JavaScript 混淆及反混淆代码工具

    介绍在我们开始学习反混淆之前,我们首先要了解一下代码混淆。如果不了解代码是如何混淆的,我们可能无法成功对代码进行反混淆,尤其是使用自定义混淆器对其进行混淆时。什么是混
  • 十个可以手动编写的 JavaScript 数组 API

    JavaScript 中有很多API,使用得当,会很方便,省力不少。 你知道它的原理吗? 今天这篇文章,我们将对它们进行一次小总结。现在开始吧。1.forEach()forEach()用于遍历数组接收一参
  • 一篇聊聊Go错误封装机制

    %w 是用于错误包装(Error Wrapping)的格式化动词。它是用于 fmt.Errorf 和 fmt.Sprintf 函数中的一个特殊格式化动词,用于将一个错误(或其他可打印的值)包装在一个新的错误中。使
  • 大厂卷向扁平化

    来源:新熵作者丨南枝 编辑丨月见大厂职级不香了。俗话说,兵无常势,水无常形,互联网企业调整职级体系并不稀奇。7月13日,淘宝天猫集团启动了近年来最大的人力制度改革,目前已形成一
  • 东方甄选单飞:有些鸟注定是关不住的

    作者:彭宽鸿来源:华尔街科技眼&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;&zwj;东方甄选创始人俞敏洪带队的&ldquo;7天甘肃行&rdquo;直播活动已在近日顺利收官。成立后一
  • 小米汽车电池信息疑似曝光:容量101kWh,支持800V高压快充

    7月14日消息,今日一名博主在社交媒体发布了一张疑似小米汽车电池信息的照片,显示该电池包正是宁德时代麒麟电池,容量为101kWh,电压为726.7V,可以预测小
  • 四年持续更迭坚持探索行业无人之境,HarmonyOS 4带来五大升级多项创新

    除了华为每年新发布的旗舰手机系列,上亿花粉更加期待鸿蒙系统每次的跨版本大更新。8月4日,HarmonyOS 4于HDC 2023正式发布,这也是该系统历经四年的再
  • 2纳米决战2025

    集微网报道 从三强争霸到四雄逐鹿,2nm的厮杀声已然隐约传来。无论是老牌劲旅台积电、三星,还是誓言重回先进制程领先地位的英特尔,甚至初成立不久的新
Top