线程池的七个核心参数

一、示例

        //创建线程池
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                2,                                                       // corePoolSize 线程池核心线程大小
                4,                                                       // maximumPoolSize 线程池最大线程数量
                5,                                                       // keepAliveTime 多余的空闲线程存活时间
                TimeUnit.MILLISECONDS,                                   // unit 空闲线程存活时间单位
                new ArrayBlockingQueue<>(2),                             // workQueue 工作队列
                new ThreadFactory() {                                    // threadFactory 线程工厂
                    @Override
                    public Thread newThread(Runnable runnable) {
                        Thread thread = new Thread(runnable);
                        thread.setName("myThread");
                        return thread;
                    }
                },
                new ThreadPoolExecutor.AbortPolicy());                   // handler 拒绝策略

二、七个核心参数

1、 corePoolSize 线程池核心线程大小

corePoolSize 是线程池中的一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。

2、maximumPoolSize 线程池最大线程数量

线程池能够容纳同时执行的最大线程数,此值大于等于1。一个任务被提交到线程池以后,首先会找有没有空闲并且存活线程,如果有则直接将任务交给这个空闲线程来执行,如果没有则会放到工作队列中,直到工作队列满了,才会创建一个新线程,然后从工作队列的头部取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列尾部。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。工作队列满,且线程数等于最大线程数,此时再提交任务则会调用拒绝策略。

3、keepAliveTime 多余的空闲线程存活时间

当线程空闲时间达到keepAliveTime值时,多余的线程会被销毁直到只剩下corePoolSize个线程为止。默认情况下:只有当线程池中的线程数大于corePoolSize时keepAliveTime才会起作用,直到线程中的线程数不大于corepoolSIze,

4、unit 空闲线程存活时间单位

keepAliveTime的计量单位

5、workQueue 工作队列

任务被提交给线程池时,会先进入工作队列,任务调度时再从工作队列中取出。

常用工作队列有以下几种:

①ArrayBlockingQueue(数组的有界阻塞队列)

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

②LinkedBlockingQueue(链表的无界阻塞队列)

按 FIFO 排序任务,可以设置容量(有界队列),不设置容量则默认使用 Integer.Max_VALUE 作为容量 (无界队列)。该队列的吞吐量高于 ArrayBlockingQueue。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize,因此使用该工作队列时,参数maxPoolSize其实是不起作用的。有两个快捷创建线程池的工厂方法 Executors.newSingleThreadExecutor、Executors.newFixedThreadPool,使用了这个队列,并且都没有设置容量(无界队列)。

③SynchronousQueue(一个不缓存任务的阻塞队列)

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

其 吞 吐 量 通 常 高 于LinkedBlockingQueue。 快捷工厂方法 Executors.newCachedThreadPool 所创建的线程池使用此队列。与前面的队列相比,这个队列比较特殊,它不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。

④PriorityBlockingQueue(具有优先级的无界阻塞队列)

优先级通过参数Comparator实现。

⑤DelayQueue(这是一个无界阻塞延迟队列)

底层基于 PriorityBlockingQueue 实现的,队列中每个元素都有过期时间,当从队列获取元素(元素出队)时,只有已经过期的元素才会出队,而队列头部的元素是过期最快的元素。快捷工厂方法 Executors.newScheduledThreadPool 所创建的线程池使用此队列。

Java 中的阻塞队列(BlockingQueue)与普通队列相比,有一个重要的特点:在阻塞队列为空时,会阻塞当前线程的元素获取操作。具体来说,在一个线程从一个空的阻塞队列中取元素时,线程会被阻塞,直到阻塞队列中有了元素;当队列中有元素后,被阻塞的线程会自动被唤醒(唤醒过程不需要用户程序干预)。

6、threadFactory 线程工厂

创建一个线程工厂用来创建线程,可以用来设定线程名、是否为daemon线程等等

7、handler 拒绝策略

  • AbortPolicy:丢弃任务并抛出 RejectedExecutionException 异常。(默认这种)
  • DiscardPolicy:丢弃任务,但是不抛出异常
  • DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程) 。也就是当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务从队尾添加进去,等待执行。
  • CallerRunsPolicy:谁调用,谁处理。由调用线程(即提交任务给线程池的线程)处理该任务,如果线程池已经被shutdown则直接丢弃
posted @   南翔技校毕业后  阅读(1075)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示