Java面试必问之线程池的创建使用、线程池的核心参数、线程池的底层工作原理

简介: Java面试必问之线程池的创建使用、线程池的核心参数、线程池的底层工作原理

Java面试必问之线程池的创建使用、线程池的核心参数、线程池的底层工作原理


一、前言

大家在面试过程中,必不可少的问题是线程池,小编也是在面试中被问啥傻了,JUC就了解的不多。加上做系统时,很少遇到,自己也是一知半解,最近看了尚硅谷阳哥的课,恍然大悟,特写此文章记录一下!如果还不了解线程池的小伙伴,一定要认真看完,你会有收获的哈!!


二、线程池创建使用

答:使用Executors看一下源码是有好多个,经常用的也就三个,今天就展示靠上的五种。

//创建一个定长线程池,超出的线程会在队列中等待
ExecutorService executorService = Executors.newFixedThreadPool(5);
//创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
//创建一个可缓存线程池,可以自动扩容,扩容大小为int最大值,因为太大可以直接理解为无限大
ExecutorService executorService2 = Executors.newCachedThreadPool();
//创建一个定长线程池,该线程池可以安排命令在给定延迟后运行,或定期执行。
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
//1.8新增-创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多少个线程在执行,不传参数默认为CPU个数
// Runtime.getRuntime().availableProcessors()查看本机CPU个数
ExecutorService executorService3 = Executors.newWorkStealingPool();


三、线程池的核心参数

//创建线程池,底层代码
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;
}

1. corePoolSize:线程池中的核心线程数,核心线程会一直存在,即使没有任务执行。

2. maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1

3. keepAliveTime:当线程数大于核心数时,这是多余空闲线程在终止前等待新任务的最长时间。(意思就是本来核心线程三个,已占满,扩展到最大线程数到5,解决完后没有线程任务了,这时设置一个时间,过了这个时间被扩展的2个非核心线程会被回收)

4. unit:keepAliveTime的时间单位。

5. workQueue:任务队列,被提交但尚未被执行的任务,相当于去饭店吃饭,餐桌满了,要在外边排队(阻塞队列)

6. threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般用默认的即可。

7. handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数。


四、线程池的底层工作原理


————————- 主要处理流程图(来源百度)

- 底层工作原理图(来源尚硅谷阳哥)

- 流程梳理

1. 在创建了线程池后,等待提交过来的任务请求。

2. 当调用execute()方法添加一个请求任务时,线程池会做如下判断:

2.1 如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务;

2.2 如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务放入队列;

2.3 如果这时候队列满了且正在运行的线程数量还小于maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务;

2.4 如果队列满了且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和拒绝策略来执行。

3.当一个线程完成任务时,它会从队列中取下一个任务来执行。

4.当一个线程无事可做超过一定的时间(keepAliveTime)时,线程池会判断:

如果当前运行的线程数大于corePoolSize,那么这个线程就被停掉;所以线程池的所有任务完成后它最终会收缩到corePoolSize 的大小。


五、总结

这样就理解很透彻了,反击尚硅谷阳哥的课程。打广告时间到了,欢迎访问小王博客站,如果你也有自己的网站留言一起做个友联!

相关文章
|
3月前
|
存储 缓存 监控
什么是线程池?它的工作原理?
我是小假 期待与你的下一次相遇 ~
264 1
|
5月前
|
数据采集 消息中间件 并行计算
Python多线程与多进程性能对比:从原理到实战的深度解析
在Python编程中,多线程与多进程是提升并发性能的关键手段。本文通过实验数据、代码示例和通俗比喻,深入解析两者在不同任务类型下的性能表现,帮助开发者科学选择并发策略,优化程序效率。
431 1
|
10月前
|
Java Linux 定位技术
Minecraft配置文件参数说明(JAVA服务器篇)
Minecraft JAVA版服务器启动后会生成server.properties配置文件,位于minecraft_server/根目录下。该文件包含多项关键设置,如游戏模式(gamemode)、最大玩家数(max-players)、难度(difficulty)等。此文档详细说明了各配置项的功能与默认值,帮助用户高效管理服务器环境。
2328 60
|
7月前
|
数据采集 网络协议 前端开发
Python多线程爬虫模板:从原理到实战的完整指南
多线程爬虫通过并发请求大幅提升数据采集效率,适用于大规模网页抓取。本文详解其原理与实现,涵盖任务队列、线程池、会话保持、异常处理、反爬对抗等核心技术,并提供可扩展的Python模板代码,助力高效稳定的数据采集实践。
370 0
|
12月前
|
监控 Kubernetes Java
阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?
本文由40岁老架构师尼恩撰写,针对一线互联网企业的高频面试题“如何确定系统的最佳线程数”进行系统化梳理。文章详细介绍了线程池设计的三个核心步骤:理论预估、压测验证和监控调整,并结合实际案例(5000qps、500ms响应时间、4核8G机器)给出具体参数设置建议。此外,还提供了《尼恩Java面试宝典PDF》等资源,帮助读者提升技术能力,顺利通过大厂面试。关注【技术自由圈】公众号,回复“领电子书”获取更多学习资料。
|
11月前
|
数据采集 Java Linux
面试大神教你:如何巧妙回答线程优先级这个经典考题?
大家好,我是小米。本文通过故事讲解Java面试中常见的线程优先级问题。小明和小华的故事帮助理解线程优先级:高优先级线程更可能被调度执行,但并非越高越好。实际开发需权衡业务需求,合理设置优先级。掌握线程优先级不仅能写出高效代码,还能在面试中脱颖而出。最后,小张因深入分析成功拿下Offer。希望这篇文章能助你在面试中游刃有余!
213 4
面试大神教你:如何巧妙回答线程优先级这个经典考题?
|
11月前
|
Java 程序员 开发者
Java社招面试题:一个线程运行时发生异常会怎样?
大家好,我是小米。今天分享一个经典的 Java 面试题:线程运行时发生异常,程序会怎样处理?此问题考察 Java 线程和异常处理机制的理解。线程发生异常,默认会导致线程终止,但可以通过 try-catch 捕获并处理,避免影响其他线程。未捕获的异常可通过 Thread.UncaughtExceptionHandler 处理。线程池中的异常会被自动处理,不影响任务执行。希望这篇文章能帮助你深入理解 Java 线程异常处理机制,为面试做好准备。如果你觉得有帮助,欢迎收藏、转发!
682 14
|
9月前
|
Java
java中一个接口A,以及一个实现它的类B,一个A类型的引用对象作为一个方法的参数,这个参数的类型可以是B的类型吗?
本文探讨了面向对象编程中接口与实现类的关系,以及里氏替换原则(LSP)的应用。通过示例代码展示了如何利用多态性将实现类的对象传递给接口类型的参数,满足LSP的要求。LSP确保子类能无缝替换父类或接口,不改变程序行为。接口定义了行为规范,实现类遵循此规范,从而保证了多态性和代码的可维护性。总结来说,接口与实现类的关系天然符合LSP,体现了多态性的核心思想。
217 0
|
11月前
|
安全 Java 开发者
【JAVA】封装多线程原理
Java 中的多线程封装旨在简化使用、提高安全性和增强可维护性。通过抽象和隐藏底层细节,提供简洁接口。常见封装方式包括基于 Runnable 和 Callable 接口的任务封装,以及线程池的封装。Runnable 适用于无返回值任务,Callable 支持有返回值任务。线程池(如 ExecutorService)则用于管理和复用线程,减少性能开销。示例代码展示了如何实现这些封装,使多线程编程更加高效和安全。
|
11月前
|
缓存 安全 Java
面试中的难题:线程异步执行后如何共享数据?
本文通过一个面试故事,详细讲解了Java中线程内部开启异步操作后如何安全地共享数据。介绍了异步操作的基本概念及常见实现方式(如CompletableFuture、ExecutorService),并重点探讨了volatile关键字、CountDownLatch和CompletableFuture等工具在线程间数据共享中的应用,帮助读者理解线程安全和内存可见性问题。通过这些方法,可以有效解决多线程环境下的数据共享挑战,提升编程效率和代码健壮性。
379 6