阿里二面:Java ThreadPool线程池,2024年最新面试题经典

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

(3) newScheduledThreadPool

==========================

传参值为corePoolSize大小,支持定时及周期性任务执行

延期执行示例:调用schedule方法,三个参数:Task,Delay,TimeUnit

public class ScheduledThreadPool {

// corePoolSize = 2

private static ScheduledExecutorService service = Executors.newScheduledThreadPool(2);

public static void main(String[] args) {

System.out.println("Thread - “+Thread.currentThread().getName()+” BEGIN "+ new Date());

service.schedule(new print(),5, TimeUnit.SECONDS);

service.shutdown();

}

static class print implements Runnable{

@Override

public void run() {

for (int i = 0; i < 10; i++) {

try{

System.out.println("Thread - “+Thread.currentThread().getName()+” Delay 5 second and sleep 2 second "+ new Date());

Thread.sleep(2000);

}catch (Exception e){

e.printStackTrace();

}

}

}

}

}

结果:

阿里二面被问Java ThreadPool线程池,看完这篇,一招怒怼面试官

定时执行示例:调用scheduleAtFixedRate方法,四个参数:Task,initialDelay,Period,TimeUnit

public class ScheduledThreadPool {

// corePoolSize = 1

private static ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

public static void main(String[] args) {

System.out.println("Thread - “+Thread.currentThread().getName()+” BEGIN "+ new Date());

service.scheduleAtFixedRate(new print(),5,3,TimeUnit.SECONDS);

}

static class print implements Runnable{

@Override

public void run() {

System.out.println("Thread - “+Thread.currentThread().getName()+” Delay 5 second and period 3 second "+ new Date());

}

}

}

结果:

阿里二面被问Java ThreadPool线程池,看完这篇,一招怒怼面试官

(4) newCachedThreadPool

=======================

可缓存线程池,如果线程池长度超过处理需要,回收空闲线程,若无可回收,则新建线程。即若前一个任务已完成,则会接着复用该线程:

public class CachedThreadPool {

private static AtomicInteger num = new AtomicInteger(0);

private static ExecutorService service = Executors.newCachedThreadPool();

public static void main(String[] args) {

countSum c = new countSum();

for (int i = 0; i < 3; i++) {

try {

service.submit©;

Thread.sleep(1000);

}catch (Exception e){

e.printStackTrace();

}

}

service.shutdown();

}

static class countSum implements Runnable{

@Override

public void run() {

for (int i = 0; i < 1000; i++) {

System.out.println("Thread - “+Thread.currentThread().getName()+” countSum= "+num.getAndIncrement());

}

}

}

}

结果:Thread.sleep(1000)即sleep一秒,上个任务完成可继续复用该线程,不需要创建新的线程

阿里二面被问Java ThreadPool线程池,看完这篇,一招怒怼面试官

若将Tread.sleep(1000)注释掉,你会发现有3个线程在跑

阿里二面被问Java ThreadPool线程池,看完这篇,一招怒怼面试官

若感兴趣可以去了解一下它们的底层源码,对于CachedThreadPool而言,可新建线程最大数量为INTEGER.MAXIMUM

2 线程池底层原理

=========

以newFixedThreadPool为例

public static ExecutorService newFixedThreadPool(int nThreads) {

return new ThreadPoolExecutor(nThreads, nThreads,

0L, TimeUnit.MILLISECONDS,

new LinkedBlockingQueue());

}

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue) {

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);

}

线程池七大参数

  • corePoolSize:线程池中的常驻核心线程数

  • maximumPoolSize:线程池中能够容纳同时执行的最大线程数,必须大于1

  • keepAliveTime:多余的空闲线程的存活时间;当前池中线程数量超过corePoolSize时,当空闲时间达到keepAliveTime时,多余线程会被销毁

  • unit:keepAliveTime的单位

  • workQueue:任务队列,被提交但尚未执行的任务

  • threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程,一般默认

  • handler:拒绝策略,表示当队列满了,并且工作线程大于等于线程池的最大线程数时如何来拒绝请求执行的runnable的策略

阿里二面被问Java ThreadPool线程池,看完这篇,一招怒怼面试官

线程池四大流程

1)创建线程池后,开始等待请求

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

  • 如果正在运行的线程数量小于corePoolSize,马上创建线程执行任务

  • 如果正在运行的线程数量大于等于corePoolSize,将该任务放入等待队列

  • 如果等待队列已满,但正在运行线程数量小于max,创建非核心线程执行任务

  • 如果队列满了且正在运行的线程数量大于max,线程池会启动饱和拒绝策略

3)当一个线程完成任务时,会从等待队列中取下一个任务来执行

4)当空闲线程超过keepAliveTime定义时间,会判断:

  • 如果当前运行线程大于corePoolSize,该线程销毁

  • 所有线程执行完任务后,线程个数恢复到corePoolSize大小

3 线程池策略及分析

==========

Note:阿里巴巴JAVA开发手册:线程池不允许使用Executors去创建线程池,而是通过使用ThreadPoolExecutor的方式自定义线程池,规避资源耗尽的风险

Executors返回的线程池对象的弊端:

1)FixedThreadPool和SingleThreadPool:

允许请求队列长度为Integer.MAX_VALUE,可能会堆积大量请求导致OOM

2)CachedThreadPool和ScheduledThreadPool:

​ 允许创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程导致OOM

拒绝策略

1)AbortPolicy

​ 直接抛出

RejectedExecutionException异常阻止系统正常运行

2)CallerRunsPolicy

​ "调用者运行"的调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量

3)DiscardPolicy

​ 该策略抛弃无法处理的任务,不予任何处理也不抛出异常。如果允许任务丢失,这是最好的一种策略

4)DiscardOldestPolicy

​ 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务

最后:学习总结——MyBtis知识脑图(纯手绘xmind文档)

学完之后,若是想验收效果如何,其实最好的方法就是可自己去总结一下。比如我就会在学习完一个东西之后自己去手绘一份xmind文件的知识梳理大纲脑图,这样也可方便后续的复习,且都是自己的理解,相信随便瞟几眼就能迅速过完整个知识,脑补回来。下方即为我手绘的MyBtis知识脑图,由于是xmind文件,不好上传,所以小编将其以图片形式导出来传在此处,细节方面不是特别清晰。但可给感兴趣的朋友提供完整的MyBtis知识脑图原件(包括上方的面试解析xmind文档)

image

除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
别清晰。但可给感兴趣的朋友提供完整的MyBtis知识脑图原件(包括上方的面试解析xmind文档)

[外链图片转存中…(img-rUr95x6i-1713370947218)]

除此之外,前文所提及的Alibaba珍藏版mybatis手写文档以及一本小小的MyBatis源码分析文档——《MyBatis源码分析》等等相关的学习笔记文档,也皆可分享给认可的朋友!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-4eVtcKFs-1713370947219)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值