Java 面试笔记 | Java 基础:线程池

前言

在日常的工作学习生活中,用一种好的方法去学习,可以更加有效,比如费曼学习法将学到的知识用自己的组织的语言表达出来,如果能够清晰明白的向别人解释清楚,那么就说明你是真的懂了,学会了。如果不能够很好的表述出来,或者被别人问倒了,那说明有不懂的细节存在,需要再次对所学的知识进行巩固。所以在平时学习的时候,可以多与别人交流,将所学的知识讲述给别人听,当没有太多人可以交流的时候,也可以通过向自己提问题的方式,看看自己能否真正的回答好这些问题,或者通过写文章,将所学的知识用自己的话写出来,这也是检验自己学习成果的一种方法。发现自己过去存在的一个比较差的习惯,在学习相关知识时,只以摘抄式的方式记笔记,而缺少复盘,没有融入自己的思考,浮于表面,当做题或者面试时接受别人的提问时,问题立马就出现了,自己没法解决这些问题,在短时间内没能很好的解释这个知识点,心里只有一些相对模糊的概念。所以什么才是真正的懂得?那就是需要看清事物与问题的本质,将所学真正的知识进行内化。在准备面试的时候也是一样,可以从不同的角度多问自己几个问题,明白了底层的逻辑和原理,记忆起来也会更加简单。这篇文章会介绍线程池相关的一些知识,从以下几个方面进行探讨:

  • 为什么要使用线程池(线程池解决了什么问题)
  • JDK中线程池的设计思想,运行流程
  • 深入了解底层源码的一些实现细节

理解线程池所要解决的问题

说到多线程,常常就与处理多个任务相关联,所以从多线程的使用场景说起,更深的层次还要理解什么是进程、线程和线程。

  • 计算机如何同时处理多个任务?

计算机如何在同一时间处理多个任务呢?在 Java 当中,可以通过创建多个线程实现。系统为每个任务都创建一个线程,将不同的任务交由不同的线程进行处理,这样就实现了同一时间处理多个任务,相当于把不同的任务分配给不同的人来处理解决。

  • 线程池的概念?主要用于解决什么问题

线程池主要用于解决线程复用的问题。如果为每个任务都分配一个线程来处理,那么当任务量很大时,就需要创建大量的线程来处理这些任务。这种方案的问题是:一方面,系统是没办法无限制的创建线程的,操作系统能够创建的线程的数量是有最大值限制的,另一方面,如果任务时多时少,那么就需要频繁的创建和销毁线程;而创建、销毁都是需要一定的系统开销的。所以就有了线程池,大致的思想如下:系统事先创建好一定数量的线程,放到一个池子里面,当一个任务过来,就从池子里拿出一个线程来处理这个任务,处理完后,在将线程放回池子当中。如果任务太多,池子里已经没有空闲的线程来处理这些任务了,就将这些没办法即时处理的任务放入到一个等待队列当中,等池子里有空闲的线程了,再从队列中取出任务进行处理,这样就实现了线程的复用,避免频繁创建和销毁线程所带来的系统开销。具体的设计思想与上面的所说的有所偏差,我们来看看 JDK 当中是如何设计和实现一个线程池的。

  • 说说 JDK 中线程池的设计思想与运行流程?

ThreadPoolExecutorJDK 中线程池的实现类,顶层接口 Executor 定义了一个执行任务的抽象方法,ExecutorService 接口在 Executor 接口的基础上,规范了线程池需要有的一些功能:比如关闭线程池(关闭后线程池不能再接收新的任务)、线程池的状态(是否关闭)、提交异步任务等。

image.png

  • 问题:1、线程池是怎么定义的,线程是如何存储在池子当中的?

JDK 当中定义了一个集合HashSet<Worker> 用来维护被创建出来的线程对象。

线程池状态( rs :标记线程池的状态,根据状态量来控制线程池应该做什么。

活跃线程数(wc :标识现在池子里的活跃线程数,以此判断要创建核心线程还是非核心线程。

JDK 中用一个 Integer 变量(ctl)来保存线程池状态和活跃线程数。通过对这个变量的与、或、非等计算,可以计算我们想要的一些数据,如通过:runStateOf 方法获取当前线程池的状态、workerCountOf 方法获取活跃线程数。阻塞队列通过workQueue.offer(command) 往任务队列当中添加任务,如果队列满了,任务无法添加到对垒当中,会返 false

  • 解释一下 JDK 线程池的构造函数参数?这些参数的作用?
    • 核心线程数:核心线程&非核心线程的概念:核心线程默认情况下会常驻于线程池当中(即使没有执行什么任务),非核心线程如果长时间闲置便会被销毁(相当于临时工,所以后面又有个非核心线程空闲的存活时间,以及存活的时间单位)。
    • 最大线程数:核心线程的数量+非核心线程的数量。
    • 非核心线程空闲时的存活时间、以及存活的时间单位。
    • 任务队列:用来暂存来不及处理的任务,线程池当中没有可以用来处理任务的线程了,那么这时候就会先将任务放入到队列当中,等待有空闲的线程来进行处理。
    • 线程池工厂:用来统一管理和创建线程。
    • 拒绝处理策略:任务无法进行处理了(任务队列满了,线程达到最大线程数,此时不允许再创建线程来处理任务了),就会执行任务拒绝处理策略。
  • 线程池的运行流程

初始时,线程池的当中的线程是空的,当一个任务过来,交由 execute 方法执行,会判断当前线程池当中的工作线程数是否小于核心线程数,优先去创建核心线程。如果核心线程已满,就会将任务暂存到任务队列当中,如果任务队列也满了,就会去创建非核心线程,如果添加非核心线程失败,就会执行任务拒绝处理策略。这里需要记住非核心线程是在队列满了之后才创建的。

  • 拒绝处理的策略有哪些?
  • 丢弃任务并抛出拒绝处理的异常信息
  • 丢弃新来的任务,但是不抛出异常
  • 丢弃队列头部(最旧的)的任务,然后重新尝试执行程序(如果再次失败,重复此过程)。
  • 直接在调用线程中执行被拒绝的任务
  • 应用到的设计模式

策略接口:RejectedExecutionHandler

具体的拒绝策略:AbortPolicyDiscardPolicyDiscardOldestPolicyCallerRunsPolicy

线程池使用的默认任务拒绝策略是:丢弃任务并抛出拒绝处理的异常信息:

private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         threadFactory, defaultHandler);

参考链接

  • JDK ThreadPoolExecutor核心原理与实践 - vivo互联网技术 - 博客园
  • https://redspider.gitbook.io/concurrent

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DataStructure.包装类简单认识泛型

包装类&简单认识泛型 【本节目标】1 包装类1.1 基本数据类型和对应的包装类1.2 装箱和拆箱1.3 自动装箱和自动拆箱 2 什么是泛型3 引出泛型3.1 语法 4 泛型类的使用4.1 语法4.2 示例4.3 类型推导(Type Inference) 5. 裸类型(Raw Type) &#xff08;了解&#xff09;5.1 说明…

C++初学者指南-2.输入和输出---文件输入和输出

C初学者指南-2.输入和输出—文件输入和输出 文章目录 C初学者指南-2.输入和输出---文件输入和输出1.写文本文件2.读文本文件3.打开关闭文件4.文件打开的模式 1.写文本文件 使用&#xff1a; std::ofstream&#xff08;输出文件流&#xff09; #include <fstream> // 文…

昂科烧录器支持KIOXIA铠侠的可编程只读存储器TH58NVG4S0HTAK0

芯片烧录行业领导者-昂科技术近日发布最新的烧录软件更新及新增支持的芯片型号列表&#xff0c;其中KIOXIA铠侠的电可擦除可编程只读存储器TH58NVG4S0HTAK0已经被昂科的通用烧录平台AP8000所支持。 TH58NVG4S0HTAK0是一个单一的3.3V 16Gbit&#xff08;18253611008位&#xff…

如何在Paperspace中使用 H100 单 GPU 和多 GPU 机器

本文将介绍如何在 DigitalOcean 的 Paperspace 平台上运行 NVIDIA H100 单卡 GPU 和 8 卡 GPU 。使用低成本的 GPU 云服务构建和扩展你的人工智能模型&#xff0c;即刻简化并加速你的机器学习工作。 如果需要了解 DigitalOcean 的 H100 GPU 云主机&#xff0c;请查看我们在 Dig…

【PA交易】BackTrader: 讨论下分析器和评测指标

前言 BackTrader的分析器主要使用的是analyzers模块&#xff0c;我们可以从Analyzers - Backtrader找到一个非常简单的示例。这个示例中使用方式很简单&#xff0c;其他分析器也可以通过如此简单封装方式进行装载。如果仅是复制粘贴官方教程&#xff0c;完全是制造互联网垃圾…

【前后端实现】AHP权重计算

AHP权重计算&#xff1a; 需求&#xff1a;前端记录矩阵维度、上三角值&#xff0c;后端构建比较矩阵、计算权重值并将结果返回给前端 比较矩阵构建 如果你想要根据上三角&#xff08;不包括对角线&#xff09;的值来构建对称矩阵&#xff0c;那么你可以稍作修改上述的generate…

Kivy tutorial 004: Making the GUI do stuff, binding to events

Kivy tutorial 004: Making the GUI do stuff, binding to events – Kivy Blog Central themes: Events and Kivy properties 中心主题&#xff1a;事件和kivy属性 We left the last tutorial with a calculator app GUI with some nice automatic behaviour, but which doe…

嵌入式C语言中常见寄存器的控制方法

使用C语言对寄存器赋值时,常常需要用到C语言的位操作方法。 把寄存器某位清零 假设a代表寄存器,且其中本来已有值。如果要把其中某一位清零且其它位不变,代码如下。 //定义一个变量 a = 1001 1111 b (二进制数)unsigned char a = 0x9f;//对 bit2 清零a &= ~(1<<…

实现批量自动化电商数据采集|商品详情页面|店铺商品信息|订单详情数据

电商数据采集是指通过技术手段获取电商平台上的商品信息、店铺信息和订单信息等数据。这些数据可以用于市场分析、竞品分析、用户行为分析等。 商品详情页面是指电商平台上展示商品详细信息的页面&#xff0c;包括商品名称、价格、图片、描述、评价等信息。通过采集商品详情页…

springboot+vue+mybatis门窗管理系统+PPT+论文+讲解+售后

如今社会上各行各业&#xff0c;都在用属于自己专用的软件来进行工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。互联网的发展&#xff0c;离不开一些新的技术&#xff0c;而新技术的产生往往是为了解决现有问题而产生的。针对于仓库信息管理方…

[学习笔记] 禹神:一小时快速上手Electron笔记,附代码

课程地址 禹神&#xff1a;一小时快速上手Electron&#xff0c;前端Electron开发教程_哔哩哔哩_bilibili 笔记地址 https://github.com/sui5yue6/my-electron-app 进程通信 桌面软件 跨平台的桌面应用程序 chromium nodejs native api 流程模型 main主进程 .js文件 node…

攻克PS之路——Day1(A1-A8)

#暑假到了&#xff0c;作为可能是最后一个快乐的暑假&#xff0c;我打算学点技能来傍身&#xff0c;首先&#xff0c;开始PS之旅 这个帖子作为我跟着B站up主学习PS的记录吧&#xff0c;希望我可以坚持下去&#xff01; 学习的链接在这里&#xff1a;A02-PS软件安装&#xff0…

Qt | 子类化 QStyle(Qt自带图标大全)

01、简介 1、把绘制自定义部件外观的步骤大致分为三大板块,如下: ①、样式元素:即指定需要绘制的图形元素(比如焦点框、按钮,工具栏等)。样式元素使 用 QStyle 类中的一系列枚举(共有 11 个枚举)进行描述。 ②、样式选项:包含了需要绘制的图形元素的所有信息,比如包含…

【QCustomPlot实战系列】QCPGraph区域高亮

使用QCPDataSelection来设置选中的区域&#xff0c;并将QCPGraph的可选择区域设置成QCP::stMultipleDataRanges void AreaPieces::initCustomPlot(QCustomPlot *parentPlot) {QVector<double> x {0, 1, 2, 3, 4, 5, 6, 7, 8};QVector<double> y {200, 560, 750…

asp.net core反向代理

新建项目 新建空白的asp.net core web项目 安装Yarp.ReverseProxy包版本为2.2.0-preview.1.24266.1 编写代码 namespace YarpStu01;public class Program {public static void Main(string[] args){var builder WebApplication.CreateBuilder(args);builder.Services.AddRev…

昇思25天学习打卡营第01天|基本介绍

作为曾经的javaer&#xff0c;本着不断学习的初心&#xff0c;报名了昇思25天的课程&#xff0c;希望自己能学会点东西的目的。 昇思MindSpore介绍 昇思MindSpore是一个全场景深度学习框架&#xff0c;旨在实现易开发、高效执行、全场景统一部署三大目标。 其中&#xff0c;…

AI大模型日报#0625:OpenAI停止不支持国家API、大模型「考上」一本、苹果上新视觉模型4M-21

导读&#xff1a;AI大模型日报&#xff0c;爬虫LLM自动生成&#xff0c;一文览尽每日AI大模型要点资讯&#xff01;目前采用“文心一言”&#xff08;ERNIE-4.0-8K-latest&#xff09;生成了今日要点以及每条资讯的摘要。欢迎阅读&#xff01;《AI大模型日报》今日要点&#xf…

【LeetCode】一、数组相关(双指针算法 + 置换)

文章目录 1、算法复杂度1.1 时间复杂度1.2 空间复杂度 2、数组3、leetcode485&#xff1a;最大连续1的个数4、leetcode283&#xff1a;移动05、leetcode27&#xff1a;移除元素 1、算法复杂度 1.1 时间复杂度 算法的执行时间与输入值之间的关系&#xff08;看代码实际总行数的…

MySQL 5.7.42 主从复制环境搭建

MySQL 5.7.42 主从复制环境搭建 下载MySQL二进制包操作系统环境配置安装过程搭建从库 本次安装环境&#xff1a; OS版本&#xff1a;Red Hat Enterprise Linux Server release 6.8 (Santiago) MySQL版本&#xff1a;5.7.42 架构&#xff1a;同一台机器&#xff0c;多实例安装搭…

洁净室(区)浮游菌检测标准操作规程及GB/T 16292-2010测试方法解读

洁净室(区)空气中浮游菌的检测。洁净区浮游菌检测是一种评估和控制洁净区(如实验室、生产车间等)内空气质量的方法。这种检测的目的是通过测量空气中的微生物(即浮游菌)数量&#xff0c;来评估洁净区的清洁度或污染程度。下面中邦兴业小编带大家详细看下如何进行浮游菌采样检测…