首页 > 其他分享 >为什么用线程池?解释下线程池参数?

为什么用线程池?解释下线程池参数?

时间:2024-07-09 15:58:02浏览次数:12  
标签:解释 task 队列 param 任务 参数 线程 public

基于:Java 线程池七个参数详解

参考:为什么使用线程池,参数解释、《Java 编程的逻辑》- 马俊昌

为什么用线程池

1、降低资源消耗:提高线程利用率,降低创建和销毁线程的消耗;

2、提高响应速度:任务来了,直接有线程可用可执行,而不用先创建线程,再执行;

3、提高线程的可管理性:线程是稀缺资源,使用线程池可以统一分配调优监控。

线程池参数

Java 并发包中线程池的实现类是 ThreadPoolExecutor,ThreadPoolExecutor 有一些重要的参数:

public class ThreadPoolExecutor extends AbstractExecutorService {
  public ThreadPoolExecutor(int corePoolSize,
                                int maximumPoolSize,
                                long keepAliveTime,
                                TimeUnit unit,
                                BlockingQueue<Runnable> workQueue,
                                ThreadFactory threadFactory,
                                RejectedExecutionHandler handler) {
      // ...
  }
}

1、int corePoolSize代表核心线程数。线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了 allowCoreThreadTimeOut。这里的最小线程数量即是 corePoolSize。任务提交到线程池后,首先会检查当前线程数是否达到了 corePoolSize,如果没有达到的话,则会创建一个新线程来处理这个任务。

2、int maximumPoolSize代表的是最大线程数。当前线程数达到 corePoolSize 后,如果继续有任务被提交到线程池,会将任务缓存到工作队列(后面会介绍)中。如果队列也已满,则会去创建一个新线程来出来这个处理。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由 maximumPoolSize 指定。

3、long keepAliveTime表示空闲存活时间。一个线程如果处于空闲状态,并且当前的线程数量大于 corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由 keepAliveTime 来设定。

4、TimeUnit unit表示 keepAliveTime 的时间单位。

5、BlockingQueue<Runnable> workQueue表示工作队列,用来存放待执行的任务。JDK 中提供了四种工作队列:

  1. ArrayBlockingQueue

    基于数组的有界阻塞队列,按 FIFO 排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。当线程池中线程数量达到 corePoolSize 后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已经是满的,则创建一个新线程,如果线程数量已经达到 maxPoolSize,则会执行拒绝策略。

  2. LinkedBlockingQueue

    基于链表的无界阻塞队列(其实最大容量为 Integer.MAX),按照 FIFO 排序。由于该队列的近似无界性,当线程池中线程数量达到 corePoolSize 后,再有新任务进来,会一直存入该队列,而基本不会去创建新线程直到 maxPoolSize(很难达到 Integer.MAX 这个数),因此使用该工作队列时,参数 maxPoolSize 其实是不起作用的。

  3. SynchronousQueue

    一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。也就是说新任务进来时,不会缓存,而是直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到 maxPoolSize,则执行拒绝策略。

  4. PriorityBlockingQueue

    具有优先级的无界阻塞队列,优先级通过参数 Comparator 实现。

6、ThreadFactory threadFactory线程工厂,用来生产线程执行任务。我们可以选择使用默认的创建工厂,产生的线程都在同一个组内,拥有相同的优先级,且都不是守护线程。当然我们也可以选择自定义线程工厂,用来设定线程名、是否为 daemon 线程等等。

7、RejectedExecutionHandler handler任务拒绝策略。当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,该如何处理呢。这里的拒绝策略,就是解决这个问题的,JDK 中提供了 4 中拒绝策略:

  1. CallerRunsPolicy

    该策略下,在调用者线程中直接执行被拒绝任务的 run 方法,除非线程池已经 shutdown,则直接抛弃任务。

    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code CallerRunsPolicy}.
        */
        public CallerRunsPolicy() { }
    
        /**
         * Executes task r in the caller's thread, unless the executor
        * has been shut down, in which case the task is discarded.
        *
        * @param r the runnable task requested to be executed
        * @param e the executor attempting to execute this task
        */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }
    
  2. AbortPolicy

    该策略下,直接丢弃任务,并抛出 RejectedExecutionException 异常。

    public static class AbortPolicy implements RejectedExecutionHandler {
        /**
         * Creates an {@code AbortPolicy}.
        */
        public AbortPolicy() { }
    
        /**
         * Always throws RejectedExecutionException.
        *
        * @param r the runnable task requested to be executed
        * @param e the executor attempting to execute this task
        * @throws RejectedExecutionException always
        */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            throw new RejectedExecutionException("Task " + r.toString() +
                                                  " rejected from " +
                                                  e.toString());
        }
    }
    
  3. DiscardPolicy

    该策略下,直接丢弃任务,什么都不做。

    public static class DiscardPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardPolicy}.
        */
        public DiscardPolicy() { }
    
        /**
         * Does nothing, which has the effect of discarding task r.
        *
        * @param r the runnable task requested to be executed
        * @param e the executor attempting to execute this task
        */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
    
  4. DiscardOldestPolicy

    该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列。

    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        /**
         * Creates a {@code DiscardOldestPolicy} for the given executor.
        */
        public DiscardOldestPolicy() { }
    
        /**
         * Obtains and ignores the next task that the executor
        * would otherwise execute, if one is immediately available,
        * and then retries execution of task r, unless the executor
        * is shut down, in which case task r is instead discarded.
        *
        * @param r the runnable task requested to be executed
        * @param e the executor attempting to execute this task
        */
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
    

标签:解释,task,队列,param,任务,参数,线程,public
From: https://www.cnblogs.com/Higurashi-kagome/p/18014128

相关文章

  • Java 线程池简单使用
    原文:使用线程池简介Java语言虽然内置了多线程支持,启动一个新线程非常方便,但是,创建线程需要操作系统资源(线程资源,栈空间等),频繁创建和销毁大量线程需要消耗大量时间。如果可以复用一组线程:┌─────┐execute┌──────────────────┐│Task1│───......
  • 内核参数优化
    linux内核参数优化(网络模块)在Linux下调整内核参数,可以直接编辑配置文件/etc/sysctl.conf,然后执行sysctl-p命令生效文件内容如下:net.ipv4.ip_forward=1net.ipv4.conf.default.rp_filter=1net.ipv4.conf.default.accept_source_route=0kernel.sysrq=0kernel.core_......
  • Franka Robot 机器人状态专有名词解释
    O_T_EE:末端执行器(EndEffector)在Base坐标系中的位姿。O_T_EE_c:最新指令的末端执行器(EE)在Base坐标系中的位姿。O_T_EE_d:期望末端执行器(EE)在Base坐标系中的位姿。F_T_EE:末端执行器在法兰坐标(flangeframe)中的位姿,一般中间会间隔一个标称末端执行器坐标系,实际安装......
  • Python多线程与多进程编程:提升程序性能的实用技巧
    前言大家好!今天我们要深入探讨Python中的多线程与多进程编程,这可是提升程序并发性能的关键技能之一。记得我在处理大量数据时,通过多线程和多进程技术,大大提高了程序的执行效率。为了让大家也能掌握这些实用技巧,我将通过多个具体案例,详细讲解如何在Python中实现多线程和多......
  • K8s 一条默认参数引起的性能问题-Pod enableServiceLinks
    问题时间线xx:xx]开发收到业务反馈接口响应超时[xx:xx]开发&SRE&中间件联合排查代码、网关、底层网络问题,无果[xx:xx] 测试环境复现排查[xx:xx] 利用差异法、排除法和经验解决,先上线[xx:xx] 根因定位 问题现象1)接口偶发性超时image-202401161814518792)容器化......
  • QT设置回调函数给python调用——参数法
    这种方法将回调函数作为python函数参数对象的方法来使用。Qt已经添加了Python库,并且能够正常调用Python的API,可以成功调用Python的代码块,这部分可以参考我另外一篇博客:QT中调用python中的函数-Henkk-博客园(cnblogs.com)1.QT相关函数定义1.1创建回调函数例如下面两个函......
  • Java线程之线程池
    1、什么是线程池?        线程池:用来管理线程对象的池子2、为什要使用线程池?               1、解决频繁的创建和销毁线程消耗的性能        2、解决大量创建线程而导致的内存泄露问题         注意:......
  • Java高级-线程池
    1.什么是线程池?用于管理线程对象的池子。2.为什么使用线程池?一个线程大约占用内存1M。 1.解决频繁创建线程和销毁线程消耗的性能。 2.解决大量创建线程而导致的内存泄漏问题。3.如何创建线程池?Java中提供了两种方式:第一种:通过工具类完成线程池的创建-:语法简......
  • 嵌入式C语言面试相关知识——CPU、进程和线程相关(相关问题很多,会经常过来更新)
    嵌入式C语言面试相关知识——CPU、进程和线程相关一、博客声明二、自问题目——CPU相关1、什么是中断?如何处理中断?2、解释上下文切换(ContextSwitch)?3、在嵌入式中如何优化CPU使用?三、自问题目——进程相关1、什么是进程?2、嵌入式系统中进程和线程的区别是什么?3、在嵌......
  • Comfyui加载大模型的注释文件,选择模型后参数设置不再迷茫
    上一篇Comfyui基础图生图工作流只需8个节点中末尾提到了两个问题,这一篇先解决第一个问题,就是我们下载了很多大模型,选择大模型时,记不住这个大模型的推荐参数怎么办?解决方法就是使用一个自定义的大模型加载节点替换原本的基础大模型加载节点观察下面这个基于上一篇基础图生图优......