多线程-线程池的核心参数介绍

线程池可以通过重用已存在的线程,降低线程创建和销毁造成的消耗。并且方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成CPU过度切换(CPU切换线程是有时间成本的,需要保持当前执行线程的现场,并恢复要执行线程的现场)

核心参数

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

创建线程池的核心参数有以下几种

  • corePoolSize:核心线程池的大小。在创建了线程池后,默认情况下,线程池中并没有任何线程,而是等待有任务到来才创建新的线程去执行任务,除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法,从这2个方法的名字就可以看出,是预创建线程的意思,即在没有任务到来之前就创建corePoolSize个线程或者一个线程;

  • maximumPoolSize:线程池最大线程数,它表示在线程池中最多能创建多少个线程,通常大于corePoolSize;

  • keepAliveTime:表示一个线程在没有任务执行时,最多保持多久会被终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;

  • unit:参数keepAliveTime的时间单位;

  • workQueue:一个阻塞队列,用来存储等待执行的任务;

    • ArrayBlockingQueue:一个基于数组的有界(不能存储无限多元素,不扩容)阻塞队列。其存取数据用的都是同一个锁,无法真正做到并行运行。在创建ArrayBlockingQueue时,我们还可以控制对象的内部锁是否采用公平锁,默认采用非公平锁。

    • LinkedBlockingQueue:一个基于链表的有界(不能存储无限多元素,不扩容)阻塞队列。其对于存取数据分别采用了独立的锁来控制数据同步,以此来提高整个队列的并发性能。但,LinkedBlockingQueue相较于ArrayBlockingQueue,在数据结构上多了一个Node对象,所以在插入删除时需要多一个创建和销毁的操作,对于效率存在一定影响。另外,构造LinkedBlockingQueue时,如果不指定容量大小,会默认一个类似无限大小的容量(Integer.MAX_VALUE),可能会导致内存溢出。

    • DelayQueue:一个无界阻塞队列。当其指定的延迟时间到了,才能够从队列中获取到该元素。往队列中插入数据的操作永远不会被阻塞,而只有获取数据的操作才会被阻塞。

    • PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。往队列中插入数据的操作永远不会被阻塞,而只有获取数据的操作才会被阻塞。所以需要注意内存溢出的情况

    • SynchronousQueue:一个不存储元素的阻塞队列。其特点在于没有容器。一个线程插入数据必须阻塞等待另一个线程取出数据。

  • threadFactory:线程工厂,主要用来创建线程。

  • handler:表示当拒绝处理任务时的策略。

    • AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

    • DiscardPolicy:也是丢弃任务,但是不抛出异常。

    • DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

    • CallerRunsPolicy:由调用线程处理该任务

四种线程池

  1. newSingleThreadExecutor创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
    
  2. newFixedThreadPool创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小java一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
    
  3. newCachedThreadPool:创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

    public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }
    
  4. newScheduledThreadPool:创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Java 中创建线程池时,可以使用 ThreadPoolExecutor 类来进行操作。ThreadPoolExecutor 类提供了多个构造函数来设置不同的参数。以下是几个常用的参数: 1. corePoolSize:线程池核心线程数,即线程池中保持活动状态的线程数。如果提交的任务数量少于核心线程数,线程池会创建新的线程来执行任务,即使有空闲线程。默认情况下,核心线程数为 0。 2. maximumPoolSize:线程池允许的最大线程数。如果提交的任务数量大于核心线程数,且等待队列已满,那么线程池会创建新的线程来执行任务,直到达到最大线程数。默认情况下,最大线程数为 Integer.MAX_VALUE。 3. keepAliveTime:非核心线程的空闲时间超过该值后会被终止。默认情况下,非核心线程会一直保持活动状态,即使没有任务执行。 4. unit:keepAliveTime 的时间单位。可以使用 TimeUnit 类提供的常量来指定,如 TimeUnit.SECONDS。 5. workQueue:用于保存等待执行的任务的阻塞队列。常用的实现类有 ArrayBlockingQueue、LinkedBlockingQueue 和 SynchronousQueue。 6. threadFactory:用于创建新线程的工厂。可以自定义实现 ThreadFactory 接口来定制线程的属性,如线程名称、优先级等。 7. handler:当线程池和工作队列都满了,并且无法处理新的任务时,用于处理新提交的任务的策略。常用的策略有 ThreadPoolExecutor.AbortPolicy(默认,抛出异常)、ThreadPoolExecutor.CallerRunsPolicy(使用调用者线程执行任务)、ThreadPoolExecutor.DiscardPolicy(丢弃任务)和 ThreadPoolExecutor.DiscardOldestPolicy(丢弃最早的任务)。 这些参数可以根据具体需求进行调整,以满足对线程池的性能和资源控制的要求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值