爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      ThreadPoolExecutor经典面试问题就在这~

      首页 知识中心 服务器 文章详情页

      ThreadPoolExecutor经典面试问题就在这~

      2024-09-24 06:30:20 阅读次数:58

      java,前端,服务器

      先来谈谈线程池


      了解线程池之前,你有哪些熟知的线程池有哪些呢?

             String(字符串常量池),MySQL JDBC,数据库连接池(DataSource);通过对他们的了解,大概知道了出现池的主要目的——减少不必要的开销,提高效率;

      为什么出现了线程池呢?

              线程出现的目的是因为进程太重量级了,导致创建线程或者销毁进程效率很低,而线程就是为了资源共享,新的线程复用之前的资源,就提高了效率,但是如果线程创建/销毁 的速率非常高,那么线程的创建/销毁带来的开销就是不可忽略的;

      线程池的基本原理是什么?

              这就像DataSource一样,再建立连接之后,同时也会保留之前的一些连接,后面若在需要建立连接,直接从池子中取就OK,这样也就减少了重新建立连接的开销;

              造一个池子,里面创建很多线程,当再次需要执行任务的时候,就不用再创建线程了,而是直接从池子中取出一个现成的线程供使用,即使该线程完成了任务,也不销毁线程,而是继续呆在线程池里准备迎接下一个任务;

      信我,ThreadPoolExecutor经典面试问题就在这~

      为什么从池子中取,要比创建线程快?

              创建线程的确需要申请一点资源,但这已经很少,很快了~但是,创建线程,是要在操作系统内核中完成的,涉及到用户态向内核态的切换操作,这个操作需要一定的开销;应用程序创建线程的是需要通过系统调用来完成的,进入操作系统内核中执行,也就是说,线程本质上就是PCB,是内核中的数据结构;

              所以这个过程大概是这样的:引用程序发起创建线程的行为,内核接到指令,在内核中完成PCB的创建,再把PCB加入调度队列中,最后返回给应用程序;(如下图)

      信我,ThreadPoolExecutor经典面试问题就在这~

              所以创建线程,是在内核中完成的,需要经历 用户态->内核态的转变,而从线程池中取线程,把线程放回线程池,这一套操作是纯用户态的逻辑

      线程池有什么优点?

      • 减少线程创建和销毁带来性能上的开销
      • 提高效率,当任务来时,可以直接使用线程,不用等待创建
      • 方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成cpu过度切换。使用线程池可以进行统一的分配,调优和监控。

      谈谈newCachedThreadPool


              在Java中,线程池的本体叫ThreadPoolExecutor,他的构造方法写起来十分麻烦,为了简化构造方法,标准库就提供了一系列工厂方法,简化使用;

      什么是工厂模式?

              new的过程中,就需要调用构造方法,有时候希望能够提供多种构造实例的方法,就需要重载构造方法来实现不同版本的实例创建,但是重载要求参数个数/类型不同,就带来了一定的限制;构造方法存在一定的局限性,为了围绕局限,就引入了工厂模式

              工厂模式,将创建产品实例的权利移交工厂,我们不再通过new来创建我们所需的对象,而是通过工厂来获取我们需要的产品。降低了产品使用者与使用者之间的耦合关系;

      不明白?来看看下图:

      信我,ThreadPoolExecutor经典面试问题就在这~

               这里创建线程池就没有显式new,而是通过Executors这个静态方法newCaChedThreadPool来完成的;

      常见用法:

              线程池的单纯使用很简单,使用submit方法,把任务提交到线程池中即可,线程池中会有线程来完成这些任务;(如下图)

      信我,ThreadPoolExecutor经典面试问题就在这~

      实现简易线程池


              想要模拟实现一个简单的线程池,就要先弄清线程池基本特性:一个线程池可以同时提交N个任务,对应的线程池中则有M个线程来完成这N个任务;

      如何把N个任务分配给M个线程呢?

              生产者消费者模型~

              这就需要一个阻塞队列,将提交的任务都放入队列中,创建M个线程来从队列中取元素,若队列为空,就阻塞等待新任务加入队列,若队列不为空,每个线程都去取任务,然后执行,执行完当前任务后,继续取下一个...直到队列为空,继续阻塞等待;

      代码如下:

      import java.util.concurrent.BlockingQueue;
      import java.util.concurrent.LinkedBlockingQueue;
      //线程池
      class MyThreadPool {
          //阻塞队列存放任务
          BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
          //存放任务
          public void submit(Runnable task) throws InterruptedException {
              queue.put(task);
          }
          //创建vip个线程来执行任务
          public MyThreadPool(int vip) {
              for(int i = 0; i < vip; i++){
                  Thread thread = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          while(true){
                              try {
                                  Runnable task = queue.take();
                                  task.run();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                          }
                      }
                  });
                  thread.start();
              }
          }
      }

      标准库中的ThreadPoolExecutor


              在Java的标准库中提供的ThreadPoolExecutor要复杂的多,构造方法可以支持很多参数,可以支持很多选项,来创造出不同风格的线程池;

              线程池的主要参数:

      ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
       TimeUnit unit, BlockingQueue<Runnable> workQueue, 
      ThreadFactory threadFactory, RejectedExecutionHandler handler)

              注意:黄字为比方,更方便理解

      参数 解释
      corePoolSize

      线程池中的核心线程数。当有请求任务来之后,若线程池已创建的线程数小于corePoolSize,无论当前线程池中是否有线程,都会创建一个新线程来执行该任务。当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中,之后就会从队列中继续取任务.

              比方一个公司的正式员工,即使摸鱼也不会被开除的那种(主要线程空闲了也不会被销毁)

      maximumPoolSize

      线程池允许的最大线程个数;当队列满了,并且创建的线程数小于maximumPoolSize,则线程池会创建新的线程来完成任务;

              比方一个公司的实习员工,摸鱼被发现了,就会被开除(非主要线程,空闲时间达到一定时间,就会被销毁)

      keepAliveTime

      空闲线程的存活时间。当线程池中线程数大于核心线程数时,线程的空闲时间如果超过线程存活时间,那么这个线程就会被销毁,直到线程池中的线程数小于等于核心线程数。

              比方一个公司的实习员工的最大摸鱼时间,相当于给实习生摸鱼的一个时间上线;

      unit keepAIiveTime的单位。
      workQueue

      任务队列。用于传输和保存等待执行任务的阻塞队列;

      (可以手动给线程池传入一个任务队列,线程池本来也有自己的任务队列,如果不传,也会自己内部创建)

      threadFactory 线程工厂。用于创建新线程。描述了线程是如何创建的,工厂对象就负责创建线程,程序员可以手动指定线程创建策略
      handler(重点) 线程拒绝策略。当线程池的线程和队列都满了(工作线程忙不过来了),若有人继续往里面添加新任务,就会执行该策略

       

      当线程池中的线程数目小于核心线程数目,此时,有新的任务来临,会继续创建线程么?为什么?

      会继续创建线程,因为当线程池中的线程数目小于核心线程数目时,说明此时系统资源并不紧张,可以继续创建线程来执行任务,并为下一次接受更多的任务提前做好准备,防止在系统资源紧张,并且还有大量任务来临的情况下,急急忙忙创建线程,这时候就是为本就紧张的系统资源上雪上加霜~

      打个比方,这就像是考试的提前一个月做好复习工作,和你考试前3天做好复习工作一样,考试前一个月,你有充足的时间准备各科考试的复习(提前创建好线程),而考试前3天复习,要么就复习好一科,要么就各科都复习不好.
       

      拒绝策略:(重点)注意:括号内为比方,更方便理解

        • static class  ThreadPoolExecutor.AbortPolicy

          被拒绝的任务的处理程序,抛出一个 RejectedExecutionException 。

                  (好比领导给员工安排了很多活,加班都干不完,这个员工干不下去了,一瞬间就情绪崩溃,晕倒了;)

          static class  ThreadPoolExecutor.CallerRunsPolicy

          一个被拒绝的任务的处理程序,直接在 execute方法的调用线程中运行被拒绝的任务,除非执行程序已经被关闭,否则这个任务被丢弃。

                 ( 好比领导给员工安排了很多任务,员工干不过来,员工就给领导说,你来干吧,这时候领导自己干,如果能干他就干了,不能干,就丢弃这个任务了;)

          static class  ThreadPoolExecutor.DiscardOldestPolicy

          被拒绝的任务的处理程序,丢弃最旧的未处理请求,然后重试 execute ,除非执行程序关闭,在这种情况下,任务被丢弃。

                  (好比领导个员工安排了任务1、任务2、任务3,领导安排到任务4的时候,员工说谈干不了,领导就说,没事,任务1不着急,你先干任务4;)

          static class  ThreadPoolExecutor.DiscardPolicy

          被拒绝的任务的处理程序静默地丢弃被拒绝的任务。

                   (好比领导个员工安排了任务1、任务2、任务3,领导安排到任务4的时候,员工说谈干不了,领导说,没事,任务4不着急,你先干之前的吧;)

      线程池的线程数目如何确定?设定成几合适?(最易错!)


              这里是不能给出具体个数的,这里面试官考察的关键是——如何设置线程数目的方法(实验+测试)

              线程池的线程数目无法确定具体数目,为什么呢?

      1. 主机的CPU的配置不确定
      2. 你的程序执行特点不确定

              你的代码里具体干了什么?是CPU密集型的任务(做了大量的算数运算和逻辑运算),还是IO密集型的任务(做了大量的读写网卡或者读写硬盘),还有的程序既需要进行很多的CPU密集型任务,又需要进行很多的IO任务,所以在实际的开发中,很难量化两种任务的比例;

              面临开发问题如何解决:如果任务全都是CPU密集型,线程数目最多也就是N,再多也没有意义,因为CPU已经占满了;但如果任务中10%是CPU密集型,90%是IO,线程数目设置成10N也没有关系;

              测试方法:实际开发处理方案是需要实验验证的!针对你的程序性能测试,分别给线程池设置成不同的数目:0.5N、N、1.5N、2N...都可以试试,然后分别记录每种情况下你的程序的一些核心性能指标和系统负载情况,最后选择一个合适的配置

      补充几种常考的线程池


      1)newSingleThreadExecutor

      单线程化线程池(newSingleThreadExecutor)的优点,串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它(此线程池保证所有任务的执行顺序按照任务的提交顺序执行)。

      Ps:因为是单线程池,我使用.shutdown()方法关闭线程池,这里不会出错,因为我是先把任务放进线程池,然后在关闭线程池,shutdown()方法会让正在执行的任务继续执行下去,没有被执行的被中断。

      曾经遇到过一次面试的时候问过:既然new Thread()和newSingleThreadExecutor()都是创建一个线程处理,为什么还需要存在单个线程的线程池呢?

      当手动去操作查看线程名称编号的时候就会发现:

      1. new Thead()的方式每次都会新建一个线程来处理,增加消耗;
      2. newSingleThreadExecutor()的方式只使用同一个线程来处理,减少了消耗;

      2)newFixedTheadPool

      newFixedTheadPool是六种常用线程池的其中一种,newFixedThreadPool的特点是他的核心线程数和最大线程数是一致的,并且是一个固定线程数的线程池。线程池的大小一旦达到最大值后,再有新的任务提交时则放入无界阻塞队列中,等到有线程空闲时,再从队列中取出任务继续执行。

      Ps:使用完成,需要手动关闭线程池

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/CYK_byte/article/details/126951400,作者:陈亦康,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:VirtualBox通过命令方式批量创建并配置虚拟机

      下一篇:spring-boot-starter-data-jpa 配置多个数据源与jpa实体类继承的问题、分页条件查询

      相关文章

      2025-05-19 09:05:01

      项目更新到公网服务器的操作步骤

      项目更新到公网服务器的操作步骤

      2025-05-19 09:05:01
      公网 , 数据库 , 文件 , 更新 , 服务器
      2025-05-19 09:04:44

      FinalShell 配置SSH密钥登陆

      FinalShell 配置SSH密钥登陆

      2025-05-19 09:04:44
      密钥 , 服务器 , 配置
      2025-05-14 10:33:16

      30天拿下Python之使用网络

      Python网络编程覆盖的范围非常广,包括:套接字编程、socketserver、HTTP和Web开发、异步编程和asyncio等。

      2025-05-14 10:33:16
      Json , TCP , 客户端 , 接字 , 服务器 , 示例 , 连接
      2025-05-14 10:02:58

      java休眠到指定时间怎么写

      java休眠到指定时间怎么写

      2025-05-14 10:02:58
      java , sleep , Thread , util , 方法
      2025-05-14 10:02:58

      java项目多端数据同步解决方案

      多端数据同步是指在多个设备(例如桌面应用、移动应用、Web应用)之间保持数据的一致性。

      2025-05-14 10:02:58
      java , Spring , WebSocket , 同步 , 数据 , 版本号
      2025-05-14 09:51:21

      python 在创建socket之后建立心跳机制

      在Python中,建立心跳机制通常用于维持客户端和服务器之间的长连接,确保连接活跃性。心跳机制通常是通过定时发送心跳包(一种小型的、特定格式的数据包)来实现的,如果在预定时间内没有收到对方的心跳响应,则认为连接可能已经中断。

      2025-05-14 09:51:21
      发送 , 客户端 , 服务器 , 服务器端 , 示例
      2025-05-13 09:53:23

      在Java、Java Web中放置图片、视频、音频、图像文件的方法

      在Java软件中放置图片,通常涉及将图片文件(如JPEG、PNG等)作为资源包含在我们的项目中,并在代码中通过适当的方式引用这些资源。这可以通过多种方式实现,但最常见的是在Java桌面应用(如Swing或JavaFX)或Web应用(如Servlet/JSP)中。

      2025-05-13 09:53:23
      JSP , URL , Web , 图片 , 服务器
      2025-05-13 09:49:12

      Java学习(动态代理的思想详细分析与案例准备)(1)

      Java学习(动态代理的思想详细分析与案例准备)(1)

      2025-05-13 09:49:12
      java , 代理 , 代码 , 对象 , 接口 , 方法 , 需要
      2025-05-09 09:21:53

      WebAPI 和 webservice的区别

      WebAPI 和 webservice的区别

      2025-05-09 09:21:53
      HTTP , 协议 , 客户端 , 服务器 , 请求
      2025-05-09 08:51:09

      git学习(1)(简单概述、代码版本控制方式(集中/分布))

      git学习(1)(简单概述、代码版本控制方式(集中/分布))

      2025-05-09 08:51:09
      git , 一个 , 代码 , 共享 , 开发人员 , 服务器 , 版本
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5256391

      查看更多

      最新文章

      项目更新到公网服务器的操作步骤

      2025-05-19 09:05:01

      FinalShell 配置SSH密钥登陆

      2025-05-19 09:04:44

      redis高可用集群搭建

      2025-05-06 09:19:12

      基于javaWeb+jsp人力资源管理系统(含文档)

      2025-05-06 09:19:00

      【Linux 从基础到进阶】Apache服务器搭建与优化

      2025-05-06 09:18:38

      【Linux 从基础到进阶】邮件服务器搭建与优化(Postfix、Dovecot)

      2025-05-06 08:30:38

      查看更多

      热门文章

      Linux运维小技巧---每日收集所有服务器信息并归档到指定服务器

      2023-03-16 07:49:58

      用ftp服务器进行yum源的设置

      2023-04-21 03:04:35

      Confluence 6 配置服务器基础地址

      2023-04-23 09:34:48

      linux中常见工具安装问题集锦

      2023-05-05 10:12:49

      linux环境日志排查,cat命令关键字查找、最近1000条、定位到指定位置

      2022-12-28 07:22:30

      在 ubuntu 中安装 Apache 2 Web 服务器

      2023-05-22 08:06:30

      查看更多

      热门标签

      服务器 linux 虚拟机 Linux 数据库 运维 网络 日志 数据恢复 java python 配置 nginx centos mysql
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      maven配置代理

      【服务器数据恢复】多次断电导致ProLiant服务器RAID模块损坏的数据恢复案例

      Nginx学习笔记 - Nginx配置深入理解

      启动U盘制作工具------------Ventoy 最新版 v1.0.96

      python paramiko 模块简介(SSH2协议)

      H2 数据库如何以服务器方式启动

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号