关于Java线程池的前前后后

1. 优秀文章整理

 

1.1 一个线程池中的线程异常了,那么线程池会怎么处理这个线程?

有的线程它死了,于是它变成一道面试题

1.2 讲述线程池原理,动态化线程池技术

Java线程池实现原理及其在美团业务中的实践

1.3 讲述动态化线程池时可能遇到的一些坑

如何设置线程池参数?美团给出了一个让面试官虎躯一震的回答。

1.4 再谈动态化调整线程池

填个坑!再谈线程池动态调整那点事。

1.5 讲述线程池mainLock锁,为何使用非线程安全set保存线程,讲述worker继承AQS的意义

面试官:你给我说一下线程池里面的几把锁。

1.6 线程池如何让最大线程数用完,再让任务进入队列(自定义队列,重写其 offer 方法)

每天都在用,但你知道 Tomcat 的线程池有多努力吗?

1.7 如何设计线程池:1000 多个并发线程,10 台机器,每台机器 4 核,设计线程池大小。

        包括普通Java线程池和Tomcat内置线程池的运行流程

一人血书,想让why哥讲一下这道面试题。

1.8 讲述线程回收的相关流程

        只要任务产生的速度大于线程轮询执行的速度,那么多余coreSize的线程就不会被回收掉

面试官一个线程池问题把我问懵逼了。

1.7 主要学习一下策略模式,责任链模式,观察者模式

实战!工作中常用到哪些设计模式?

1.8 线程池如何知道一个线程的任务已经执行完成?

1)可以使用submit + Future.get()

2)使用CountDownLautch的await + countDown

总结:因为线程池中的任务执行本身是没有返回值的,所以要想知道任务的执行状态,就只能通过这种阻塞 + 唤醒的方式,方式1和2原理都是如此;

【Java面试】面试被问:线程池如何知道一个线程的任务已经执行完成?_哔哩哔哩_bilibili

1.9 为什么线程池的submit不抛出异常?

1)使用submit提交的任务,执行的call()方法时外面被try catch住了,然后把异常结果set到了outCome中,需要通过Future.get()才能拿到异常信息;所以,使用使用submit提交的任务,执行中抛出异常时,是不会在控制台把异常信息打印出来的;

大厂面试题:为什么线程池的submit不抛出异常?_哔哩哔哩_bilibili

2.0 多线程使用的3个坑

其中有一个小技巧:给线程池加一个简单的监控

03 线程池:业务代码最常用也最容易犯错的组件.md

2. 线程池原理篇

2.1 ThreadPoolExecutor运行流程

图片

从运行流程,就可以看线程池的功能核心设计细分为几个模块,包括:

  1. 任务调度:任务分配
  2. 任务缓存:任务管理
  3. 任务申请:实现任务管理模块和线程管理模块的通信,对应源码的getTask()
  4. 线程管理:Worker线程,Worker线程增加,Worker线程回收
  5. 任务拒绝:线程池的保护部分,保护机制

2.2 线程管理模块

2.2.1 Worker线程

Worker执行任务的模型如下图所示:        

图片

        firstTask用它来保存传入的第一个任务,这个任务可以有也可以为null。如果这个值是非空的,那么线程就会在启动初期立即执行这个任务,也就对应核心线程创建时的情况;如果这个值是null,那么就需要创建一个线程去执行任务列表(workQueue)中的任务,也就是非核心线程的创建。

2.2.2 Worker线程增加

        增加线程是通过线程池中的addWorker方法,该方法的功能就是增加一个线程,该方法不考虑线程池是在哪个阶段增加的该线程,这个分配线程的策略是在上个步骤完成的,该步骤仅仅完成增加线程,并使它运行,最后返回是否成功这个结果。

        addWorker方法有两个参数:firstTask、core。firstTask参数用于指定新增的线程执行的第一个任务,该参数可以为空;core参数为true,表示在新增线程时会判断当前活动线程数是否少于corePoolSize,false表示新增线程前需要判断当前活动线程数是否少于maximumPoolSize,其执行流程如下图所示:

        addWorker方法,会创建一个包含一个Thread线程的Worker,并把该线程start启动。并且该线程创建时,Worker自身会以this指针的形式传递给该Thread线程。Worker实现了Runnable,该Runnable内部的run() -> runWorker() -> getTask() -> task.run();

图片

2.2.3 Worker线程回收

回收过程如下图所示:

图片

线程回收的工作是在processWorkerExit()完成的。processWorkerExit()被runWorker()调用:

图片

2.2.4 线程执行

在Worker类中的run方法调用了runWorker方法来执行任务,runWorker方法的执行过程如下:

  1. while循环不断地通过getTask()方法获取任务。

  2. getTask()方法从阻塞队列中取任务。

  3. 如果线程池正在停止,那么要保证当前线程是中断状态,否则要保证当前线程不是中断状态。

  4. 执行任务。

  5. 如果getTask结果为null则跳出循环,执行processWorkerExit()方法,销毁线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值