• 面试问我线程池?还好我早有应对


    目录

    一、线程池

    1、线程池是什么

    2、标准库中的线程池

    3、线程池工作流程

    4、拒绝策略的解析

    5、线程池的实现


    一、线程池

    1、线程池是什么

    线程池顾名思义就是类似一个“池子”里边存着线程,我们需要处理任务的时候就从中取出一个线程,搭载上我们的任务去执行就好了。那为什么要有线程池呢?

    看到这里线程池的作用已经很明显了:减少每次启动,销毁线程的损耗。

    2、标准库中的线程池

    我们先介绍其中一些参数的意义:

    1、corePollSize:核心线程最大数量,可以理解为正式员工,一般来说,正式员工不会被解雇(销毁),但当 allowCoreThreadTimeout 设为 true 时,正式员工摸鱼时长超过 keepAliveTime(下边会讲)也会被销毁。

    2、maximumPollSize:线程池中 正式员工 + 临时工 的最大数量,这是我们线程池中最多的线程数,一旦达到这个数值,后序任务就会阻塞

    3、keepAliveTime:员工摸鱼时长,如果临时工超过摸鱼时长都没有分配任务,临时工就会被解雇(销毁),当然,如果 allowCoreThreadTimeout 设置为true,正式工摸鱼达到时长也会被解雇

    4、unit:unit 其实是keepAliveTime 的时间单位

    5、workQueue: 任务队列(本质上就是阻塞队列),存的是可执行的对象

    6、threadFactory:线程工厂,我们可以介入到如何招聘员工(创建线程的方式)

    7、handler:拒绝策略,有四种拒绝策略,后边会详细说明

    3、线程池工作流程

    首先上图:

    可以看到图很难看懂,下边是针对流程的梳理:

    我们在线程池加入一个任务时,如果正式员工的数量还没到上限,我们就优先招一个正式工去执行任务,如果正式工满了,我们就去看阻塞队列满没满,优先把任务放到阻塞队列中,如果此时阻塞队列也满了,我们就只能招聘临时工去执行任务,如果员工总的数量都满了,我们就只能采取拒绝策略了。

    在每个临时工执行完自己的任务后,我们都要看它是不是长时间摸鱼,以此回收它,当然,如果设置了 allowCoreThreadTimeout 那么正式员工摸鱼也会被解雇。

    4、拒绝策略的解析

    当线程池的 员工总数 达到最大值,此时如果还有新来的任务,我们就要采用拒绝策略,拒绝策略有四种

    1、AbortPolicy:直接抛异常

    2、CallerRunsPolicy:谁添加任务谁自己做(自己动手丰衣足食)

    3、DiscardPolicy:丢弃任务,不抛异常。(谁也不知道)

    3、DiscardOlderstPolicy:丢弃队列中最早的未处理任务,执行新任务

    5、线程池的实现

    Excutors创建线程的几种方式:

    newFixedThreadPoll:创建固定线程数的线程池

    newCachedThreadPoll:创建线程数目动态增长的线程池

    newSingleThreadExcutor:创建只包含单个线程的线程池

    newScheduledThreadPoll:设定延迟时间后执行命令

     

    1. import java.util.ArrayList;
    2. import java.util.List;
    3. import java.util.concurrent.BlockingQueue;
    4. import java.util.concurrent.LinkedBlockingQueue;
    5. public class ThreadDemo2 {
    6. static class Worker extends Thread{
    7. private BlockingQueue<Runnable> queue = null;
    8. public Worker(BlockingQueue<Runnable> queue){
    9. this.queue = queue;
    10. }
    11. @Override
    12. public void run() {
    13. while (true){
    14. try {
    15. Runnable command = queue.take();
    16. command.run();
    17. } catch (InterruptedException e) {
    18. e.printStackTrace();
    19. }
    20. }
    21. }
    22. }
    23. static class ThreadPool{
    24. // 阻塞队列 用来组织任务
    25. private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
    26. // 用来存放当前的工作线程
    27. private List<Worker> workers = new ArrayList<>();
    28. // 最大工作线程数
    29. private final int MAX_WORKER_COUNT = 10;
    30. public void submit(Runnable command) throws InterruptedException {
    31. if(workers.size() < MAX_WORKER_COUNT){
    32. // 当前工作线程不足 创建新的线程
    33. // Worker内部需要获取到队列的内容,就需要创建一个构造方法.
    34. Worker worker = new Worker(queue);
    35. worker.start();
    36. workers.add(worker);
    37. }
    38. queue.put(command);
    39. }
    40. }
    41. public static void main(String[] args) throws InterruptedException {
    42. ThreadPool pool = new ThreadPool();
    43. pool.submit(new Runnable() {
    44. @Override
    45. public void run() {
    46. System.out.println("hello");
    47. }
    48. });
    49. }
    50. }

    此处源码来自大佬:(297条消息) 操作系统 --- 多线程(初阶)_wwzzzzzzzzz的博客-CSDN博客_操作系统多线程icon-default.png?t=M4ADhttps://wangzhi430.blog.csdn.net/article/details/123524983?spm=1001.2014.3001.5502

  • 相关阅读:
    Spring中的循环依赖问题
    package-lock.json 有什么作用,如果项目中没有它会怎么样,举例说明
    介绍使用Photoshop制作ico图标
    纳米金颗粒修饰核酸产品|碳纳米管载核酸-DNA/RNA材料|解析说明
    学习笔记-公有云安全
    VUE前端HTML静默打印(不弹出打印对话框)PDF简单方案
    SQL Server教程 - T-SQL-游标(CURSOR)
    Springboot毕设项目鲜花售卖管理系统593y6java+VUE+Mybatis+Maven+Mysql+sprnig)
    整合minio时出现的错误
    【Java】方法重写
  • 原文地址:https://blog.csdn.net/qq_59539549/article/details/125014470