【多线程初阶五】线程池常考面试题

news2025/1/23 7:55:42

目录

🌟一、线程池

🌈1、线程池是什么?

🌈2、为什么要使用线程池?

🌈3、怎么使用线程池?

        1、使用标准库中的线程池(6种)——>不推荐使用。  

        2、自定义一个线程池(重点)


🌟一、线程池

🌈1、线程池是什么?

        简单理解就是:在线程池中已经存在了一些创建好的线程,只需要往线程池中提交任务即可,当任务被提交到线程池之后,任务就会被自动执行。当程序启动的时候,如果发现有任务就立刻执行,没有任务就阻塞等待。

🌈2、为什么要使用线程池?

        线程池最大的好处就是减少频繁创建和销毁线程的系统的开销,从而提高效率。


🌈3、怎么使用线程池?

        1、使用标准库中的线程池(6种)——>不推荐使用。  

        (1)6种方法     

public static void main(String[] args) {
        // 1. 用来处理大量短时间工作任务的线程池,如果池中没有可用的线程将创建新的线程,如果线程空闲60秒将收回并移出缓存
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        // 2. 创建一个操作无界队列且固定大小线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        // 3. 创建一个操作无界队列且只有一个工作线程的线程池
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        // 4. 创建一个单线程执行器,可以在给定时间后执行或定期执行。
        ScheduledExecutorService singleThreadScheduledExecutor = Executors.newSingleThreadScheduledExecutor();
        // 5. 创建一个指定大小的线程池,可以在给定时间后执行或定期执行。
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
        // 6. 创建一个指定大小(不传入参数,为当前机器CPU核心数)的线程池,并行地处理任务,不保证处理顺序
        Executors.newWorkStealingPool();
    }

  ❓面试题1:如何自定义线程池?  创建线程池时构造方法的参数及含义?(重点)

        (1)  通过工厂方法获取的线程池,最终都是ThreadPoolExecutor对象。通过创建(new)一个 ThreadPoolExecutor的对象自定义线程池。

        (2)参数含义

 1️⃣corePoolSize:核心线程数,创建线程池时包含的最小线程数量。(一次性全部创建完成)

 2️⃣maxminPoolSize:最大线程数。当线程不够用时,允许系统可以创建的最多线程数(最大线程数-核心线程数)。

 3️⃣keepAliveTime:临时线程空闲的时长。

 4️⃣Timeunit unit:空闲的时间单位和keepAliveTime一起使用。

 5️⃣BlockingQueue:存放任务的阻塞队列。

 6️⃣threadfactory:线程工厂,规定了怎么去创建线程。用系统默认的就行。

 7️⃣RejectedExecutionHander hander:拒绝策略,触发时机:当线程池处理不了过多的任务时。


理解上述过程:

🌰1:吃火锅~

(1)火锅店一共有10张桌子(对应核心线程数);

(2)中午2.00去,店里没有人,随便坐,此时店里的桌子足够招待客人;(对应:当任务量较小时,核心线程完全可以处理)

(3)到了下午5/6点,到饭点了,来吃饭的人逐渐增多,此时10张桌子就已经坐满了(对应:核心线程数已满);

(4)再来的顾客就要排号(对应:往阻塞队列里面添加任务)

(5)当顾客人数越来越多,老板就在店门口加了5张桌子(对应:创建的临时线程数)

(6)当顾客慢慢吃完了,也没有新来的排号的顾客时,门口的5张桌子就空闲下来了,说明店里的10张桌子完全可以处理顾客的人数;

(7)当老板等待30min后(对应:线程的空间时间和时间单位)仍然没有新来的顾客,门口的桌子用不上了,那就可以收回了(对应:回收临时线程)

(8)当在用餐高峰期,门口的桌子也用完了,那对于新来的顾客执行拒绝策略。


 上述过程总结:

 

❓面试题2:描述一下线程池的工作原理?(上述7个参数是如何搭配使用的?)(重点)

(1)当任务添加到线程池中,先判断当前任务数是否大于核心线程数;

(2)如果任务数小于等于核心线程数,则直接执行任务,否则加入阻塞队列中等待;

(3)当阻塞队列满了之后,按照指定的最大线程数创建临时线程(最大线程数-核心线程数);

(4)当阻塞队列满了之后,而且临时线程也已经创建完成,再次提交任务的时候,就会执行拒绝策略

(5)当任务量减少且核心线程数完全够执行,临时线程达到一定的空间时长之后就会被回收。

理解拒绝策略:

❓问题3:为什么不推荐使用系统自带的线程池?

❓ 面试题3:创建线程池的时候,指定的核心线程数一般是多少比较合适?

(1)这个没有一个准确的答案,要根据业务场景和计算机配置来决定;

(2)对于计算密集型的程序,那么线程数可以适当的增大;对于IO密集型的程序,取决于磁盘的读写效率,线程数过大也不会提高程序的效率;

(3)还需要考虑COU的核心数量是多少;

(4)最终要通过测试对比,来确定一个合适的线程数。

(2)演示使用JDK提供的方法实现线程池

(1)创建线程

(2)提交线程

        threadPool.submit();

//模拟实现线程池:一共有10个任务,线程池有3个线程。将任务提交到线程池,期望输出结果:每次这10个线程都是由线程池中的三个线程执行的。
    public static void main(String[] args) throws InterruptedException {
        //1、创建一个大小为3的线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        //2、提交任务到线程池
        for (int i = 0; i < 10; i++) {
            int taskId = i;
            //3、表示要执行的任务
            threadPool.submit(()->{
                System.out.println("正在执行任务"+taskId+","+Thread.currentThread().getName());
            });
        }
        //4、等待任务执行
        TimeUnit.SECONDS.sleep(5);
        System.out.println("任务执行结束");
    }


  2、自定义一个线程池(重点)

🍀 创建一个线程池需要满足的条件:

        (1)需要提交任务到线程池,那么就要有一种数据结构来保存我们提交的任务;(考虑用阻塞队列实现)

        (2)创建线程时需要指定初始线程数量,这些线程不停的扫描阻塞队列,一旦有任务就立刻执行。(可以考虑用线程池对象的构造方法,接收要创建线程的数据,并在构造方法中完成线程的创建)   

自定义实现线程池: 

public class a03_MyThreadPool {
    //目标:用阻塞队列模拟线程池(创建一些线程表示线程池中已有的工作线程),往线程池中提交任务后,任务被工作线程执行
    //1、定义一个阻塞队列(就代表线程池),初始化容量为3。--------不理解。注意类型为Runnable
    BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(3);
    //2、核心方法:对外提供一个方法,用来往线程池中提交任务
    public void submit(Runnable task) throws InterruptedException {
        queue.put(task);
    }
    //3、构造方法中,就要创建一些工作线程,让这些工作俩执行上述提交的任务
    public a03_MyThreadPool(int capacity){
        if(capacity <= 0){
            throw new RuntimeException("线程池的数量不能小于0");
        }
        //4、在线程池中创建一些工作线程(创建的个数就是初始化线程池给定的容量数)
        for (int i = 0; i < capacity; i++) {
            Thread thread= new Thread(()->{
                //5、不停的扫描
                while (true){
                    try {
                        //6、取出提交的任务,并执行
                        Runnable task = queue.take();
                        task.run();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            //7、启动线程
            thread.start();
        }
    }
}

测试类:

public static void main(String[] args) throws InterruptedException {
        //1、创建一个大小为3的线程池
        a03_MyThreadPool threadPool = new a03_MyThreadPool(3);
        //2、提交任务到线程池
        for (int i = 0; i < 10; i++) {
            int taskId = i;
            //3、表示要执行的任务
            threadPool.submit(()->{
                System.out.println("正在执行任务"+taskId+","+Thread.currentThread().getName());
            });
        }
        //4、等待任务执行
        TimeUnit.SECONDS.sleep(5);
        System.out.println("任务执行结束");
    }

执行结果:


不要焦虑,行动解决焦虑!

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

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

相关文章

【移动端网页布局】flex 弹性布局子项目属性 ① ( flex 属性用法说明 | 代码示例 : 占有剩余布局 / 平均分成若干等份 )

文章目录 一、flex 子项目常用属性1、子项目常用属性介绍2、flex 属性用法说明 二、flex 属性代码示例1、代码示例 - 左右两侧 100 像素 / 中间元素占有所有剩余布局3、代码示例 - 平均分成三等份 一、flex 子项目常用属性 1、子项目常用属性介绍 flex 子项目 的常用属性 : fl…

FL Studio 2023年最新安装使用图文教程,FL Studio 21怎么激活解锁?

Image-Line宣布针对Win和Mac版本的数字音频工作站FL Studio的21版本更新。FL Studio2023是一个完整的软件音乐制作环境或数字音频工作站&#xff08;DAW&#xff09;。代表超过 25年的创新发展&#xff0c;它包含了您在一个包装中编排&#xff0c;编排&#xff0c;录制&#xf…

查询数据(数据库)——简单查询

目录 1&#xff0e;最简单的查询 &#xff08;1&#xff09;查询指定列 &#xff08;2&#xff09;查询所有列 &#xff08;3&#xff09;查询计算列 &#xff08;4&#xff09;为列起别名 &#xff08;5&#xff09;使用DISTINCT关键字消除重复元组 2&#xff0e;查询满…

Kyligence Zen产品体验--小白也能快速上手的指标平台

一、写在最前 啥是Kyligence Zen? Kyligence Zen 是基于 Kyligence 核心 OLAP能力打造的一站式指标平台。凭借集业务模型、指标管理、指标加工、数据服务等于一体的解决方案&#xff0c;Kyligence 协助过多家金融、零售、制造企业客户搭建企业级指标平台。Kyligence Zen 是 K…

常见八种排序实现方法

常见八种排序实现方法 前言快速排序堆排序冒泡排序代码 选择排序代码部分 插入排序思路讲解代码部分 希尔排序代码部分思路讲解 归并排序递归思路讲解代码部分 非递归梭哈代码部分思路讲解 非梭哈代码部分 计数排序代码部分 前言 这里的快速排序和堆排序博主以前都写过&#xf…

绝地求生 压枪python版

仅做学习交流&#xff0c;非盈利&#xff0c;侵联删&#xff08;狗头保命) 一、概述 1.1 效果 总的来说&#xff0c;这种方式是通过图像识别来完成的&#xff0c;不侵入游戏&#xff0c;不读取内存&#xff0c;安全不被检测。 1.2 前置知识 游戏中有各种不同的枪械&#x…

算法修炼之练气篇——练气十四层

博主&#xff1a;命运之光 专栏&#xff1a;算法修炼之练气篇 前言&#xff1a;每天练习五道题&#xff0c;炼气篇大概会练习200道题左右&#xff0c;题目有C语言网上的题&#xff0c;也有洛谷上面的题&#xff0c;题目简单适合新手入门。&#xff08;代码都是命运之光自己写的…

基于 LHS 、 BR 与K-means的风电出力场景分析研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

多线程基础总结

1. 为什么要有多线程&#xff1f; 线程&#xff1a;线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中实际运行单位。 进程&#xff1a;进程是程序的基本执行实体。 什么是多线程&#xff1f; 有了多线程&#xff0c;我们就可以让程序同时做…

Java学习路线【看看ChatGPT怎么说】

目录 1、介绍情况2、路线简述3、Java初学者路线4、Java高级开发路线5、安卓开发 1、介绍情况 本文主体内容是chatGPT生成的&#x1f609; 先说结论&#xff1a;chatGPT写出来的路线&#xff0c;深度比较一般&#xff0c;但是对于初学者而言&#xff0c;具有不错的参考价值。…

【机器学习】XGBoost 详细解读 (集成学习_Boosting_GBM)

【机器学习】XGBoost 详细解读 &#xff08;集成学习_Boosting_GBM&#xff09; 文章目录 【机器学习】XGBoost 详细解读 &#xff08;集成学习_Boosting_GBM&#xff09;1. 介绍2. 基本原理3. 目标函数&#xff08;二阶泰勒展开求解&#xff09;3.1 基础的目标函数3.2 二阶泰勒…

error: LNK2001: 无法解析的外部符号 “public: virtual struct QMetaObject const * __cdecl

Qt系列文章目录 文章目录 Qt系列文章目录前言一、QtCreator中qmake命令是什么&#xff1f;2.解决 前言 我在代码中加入了对应的信号和槽&#xff0c;但编译仍然报错&#xff1a; #ifndef PROJECTWIN_H #define PROJECTWIN_Hnamespace Ui { class ProjectWin; }ProjectWin类声…

Google Bard使用初体验,与ChatGPT比较到底怎么样

文章目录 Google Bard 介绍如何使用Google bardbard和ChatGPT3.5的区别 本文讲述了Google bard的入门教程和使用技巧&#xff0c;并且与竞争对手ChatGPT进行了一个全方面的比较。这是 Google 不能输的战役&#xff0c;也是全面 AI 的时刻。 Google Bard 介绍 Google Bard已经于…

【数据结构】链表(C语言)

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c语言系列专栏&#xff1a;c语言之路重点知识整合 &#x…

JUC之集合类

JUC包提供了一些并发安全的集合类&#xff0c;用于在多线程环境下进行共享数据的操作&#xff0c;以解决多线程间的竞争条件和线程安全问题。 CopyOnWriteArrayList 相当于线程安全的ArrayList public class ListTest {public static void main(String[] arge){List<Strin…

【项目-前后端交互-项目】表白墙【servlet实践】

【项目—前后端交互 案例】表白墙 代码示例: 服务器版表白墙1. 准备工作2. 约定前后端交互接口3. 实现服务器端代码创建 Message 类创建 MessageServlet 类 4. 调整前端页面代码5. 数据存入文件.6. 数据存入数据库1) 在 pom.xml 中引入 mysql 的依赖2) 创建数据库, 创建 messag…

ModuleNotFoundError: No module named ‘Multiscaledeformableattention‘

在实现DINO Detection方法时&#xff0c;我们可能会遇到以上问题。因为在DeformableAttention模块&#xff0c;为了加速&#xff0c;需要自己去编译这个模块。 如果你的环境变量中能够找到cuda路径&#xff0c;使用正确的torch版本和cuda版本的话&#xff0c;这个问题很容易解…

代码随想录算法训练营第三十九天 | 不同路径(挺简单的)

62.不同路径 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;动态规划中如何初始化很重要&#xff01;| LeetCode&#xff1a;62.不同路径_哔哩哔哩_bilibili 状态&#xff1a;能直接做出来。 思路 机器人从(1 , 1) 位置出发&#xff0c;到(m, n)终…

对抗训练方法:保卫人工智能的盾牌

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

【纳什博弈、ADMM】基于纳什博弈和交替方向乘子法的多微网主体能源共享研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…