首页 > 编程语言 >【后端面经-java】java线程池满的处理策略

【后端面经-java】java线程池满的处理策略

时间:2023-06-21 09:35:30浏览次数:72  
标签:池满 java 处理 调度 线程 等待 CPU

目录

1. 线程池介绍

1.1 基本作用

对多个线程使用的资源进行集中管理。

  • 降低资源消耗:
    • 复用线程,降低线程创建和销毁造成的消耗;
  • 线程资源管理
    • 提高管理效率;
  • 提高线程的响应速度
    • 在线程池中随时等待被执行,CPU不用等到线程创建时间;

1.2 处理流程

当一个线程进入线程池之后,会进行如下的处理步骤:

  • 首先查看核心线程池是否满

    • 如果没满,线程将在此处等待被调度执行;
  • 如果核心线程池满了,那么查看队列是否满了

    • 如果没满,线程在这里等待进入核心线程池;
  • 如果队列也满了,那么查看临时线程池是否满了

    • 如果没满,创建临时线程来处理任务。
  • 如果临时线程池也满了,那就要根据2.线程池满的处理策略进行线程处理。
    如下图所示:
    在这里插入图片描述

当调度者需要调度一个线程的时候,按照如下步骤:

  • 核心线程池中获取一个线程,执行任务;
  • 如果线程处于等待态,获取下一个线程继续执行;
  • 某一个任务执行完毕后,线程返回就绪态而不是终止态,放入线程池中复用。

1.3 线程池大小设置

  • CPU操作密集的任务

    • 由于线程操作多半需要占据CPU资源,因此一个线程运行的过程中基本上很少会出现某一线程进入等待态而调度下一个线程的情况;
    • 因此CPU调度线程的速度偏慢,因此线程池大小不应过大,一般为CPU核心数+1;这样可以保证CPU的效率最高;
    • 如果线程池容量过大,那么不仅对CPU运行是一个很大的负担,而且大量线程都处于等待运行的阶段,等待时间过长,可能出现响应过慢的情况。
  • I/O操作密集的任务

    • 对于I/O操作密集的任务,线程对于CPU的资源占用常常被I/O等操作打断,此时线程进入等待态,CPU继续调度下一个线程;
    • CPU调度线程的速度偏快,线程池大小可以尽量大一点,这样能够保障CPU资源的利用率,提高线程执行效率;
    • 如果线程池容量过小,CPU在调度一段时间之后,所有线程都进入等待态,此时就会出现CPU空等的情况,不利于资源有效利用。
  • 注意

  • 对于就绪态等待态等线程状态和生命周期的介绍,可参考这篇博客

1.4 线程池参数

线程池的构造方法如下所示:

public ThreadPoolExecutor(int corePoolSize,
                        int maximumPoolSize,
                        long keepAliveTime,
                        TimeUnit unit,
                        BlockingQueue<Runnable> workQueue,
                        ThreadFactory threadFactory,
                        RejectedExecutionHandler handler);

线程池的创建包含以下参数:

  • corePoolSize:核心线程池容量大小
    • 如前文所述,线程进行核心线程池即可等待调度执行
  • maximumPoolSize:最大线程池大小
    • 通过这个来判断线程池是否已满。
      MaximumPoolSize = CorePoolSize + WorkQueue + 临时线程池大小
      
  • workQueue:任务队列
    • 无法进入核心线程池的线程将进入任务队列等待进入池中;
    • 阻塞队列对象,一般需要设定容量大小
  • keepAliveTime:线程存活时间
    • 线程池已满的情况下,空闲多余的线程有个存活时间,超过这个时间还没有进入核心线程池,那么将被丢弃;
  • timeUnit:线程存活时间单位
    • 配合线程存活时间使用;
  • handler:拒绝策略
    • 当前线程池满了之后(超过maxmumPoolSize),对于新的线程的处理策略,
    • 包括四种,在2.1 默认--拒绝策略handler有详细论述
  • threadFactory:线程工厂
    • 用于创建线程池中的线程。

2. 线程池满的处理策略

2.1 默认--拒绝策略handler

线程池满了之后,一般的处理方式是丢弃某一线程,并且抛出异常。
Handler有四种策略:

  • AbortPolicy:直接抛出异常RejectedExecutionException
  • DiscardPolicy:直接丢弃任务,但是不抛出异常( 默认)。
  • DiscardOldestPolicy:丢弃队列中最旧的任务,然后重新尝试执行任务;
  • CallerRunsPolicy:由调用线程处理该任务。

3. 参考资料

参考博客-1
参考博客-2
参考博客-3
参考博客-4

标签:池满,java,处理,调度,线程,等待,CPU
From: https://www.cnblogs.com/CrazyPixel/p/17495414.html

相关文章

  • Java基础之“Double类型,保留两位小数,避免因小数过长导致乱码问题”
    保留两位小数方案一DoubletotalSaleAmount=4.174558045899999E7;DecimalFormatdf=newDecimalFormat("#.##");System.out.println("df.format(totalSaleAmount)="+df.format(totalSaleAmount));方案二DoubletotalSa......
  • java~字节码操作Javassist
    Javassist是一个开源的Java字节码操作库,它提供了一组简单而强大的API,用于在运行时修改和生成Java字节码。Javassist的名称是"JavaProgrammingAssistant"的缩写,它的目标是简化对字节码的操作,使开发人员能够更轻松地实现动态代码生成和修改。Javassist的主要特点包括:简单易用:J......
  • javaee项目
       ......
  • 如何获取多线程执行的返回值,多线程的第三种实现方式。
    多线程的第三种实现方式主要有以下步骤。1、创建一个类#MyCallable实现Callable接口。在泛型中指定多线程执行后要返回的数据类型2、在MyCallable方法种重写call方法,此方法的内容,便是多线程的执行内容。类似于run方法。3、将MyCallable对象实例化。4、创建FutureTask<Integer>......
  • java递归创建目录
    importjava.io.File;publicclassCreateDirectory{publicstaticvoidmain(String[]args){Stringpath="D:\\heap\\d\\c\\e";createDirectory(path);}publicstaticvoidcreateDirectory(Stringpath){......
  • java-http携带json参数访问接口
    一个接收map的接口@RequestMapping("kkw")publicStringkkw(@RequestBodyMap<String,Object>map){if(map!=null){System.out.println(JSONObject.toJSONString(map));;}return"success";}pac......
  • java调用pmml算法模型
    ==背景==项目需要调用算法模型,用于优化工艺参数。 ==思路==根据团队不具备算法训练能力的特点,技术上采用“训练与使用分离”的策略,即:模型训练寻找第三方渠道,将训练好的算法模型导出pmml文件,然后通过java调用模型文件。 ==代码样例==【准备模型】找朋友要了了一个测试用......
  • 简单记录下 Spring Boot 使用虚拟线程Virtual Threads(Java的协程)的方法
    在之前的文章中,简单描述了将springboot2.x升级springboot3.1的版本的过程。本文将简单介绍如何在spring中引入虚拟线程,在文章最后会放上一些关于虚拟线程的官方参考资料。JDK22会引来重要特性,VirtualThreads也就是协程功能。与主流的async、await方案(C#、JS等语言)相比......
  • 为什么很多人说不建议学JAVA,说很难找到工作?
    个人感觉这个观点有点片面。虽然国内的IT市场已经变得越来越竞争激烈,但Java作为一种应用广泛的编程语言仍然非常受欢迎。Java可以应用于Web开发、移动开发、大数据处理等多个领域,具有广泛的用途和良好的生态圈。因此,在Java领域拥有一定技能的人才仍然有很多岗位可以选择。如果......
  • Java的7种位运算符
    位运算符在Java语言中,提供了7种位运算符,分别是按位与(&)、按位或(|)、按位异或(^)、取反(~)、左移(<<)、带符号右移(>>)和无符号右移(>>>)操作符语义描述运算规则&  按位与    二进制数据按位与操作如果两个二进制位上的数都是1,那么运算结果为1,其他情况运算结果......