JAVA应用】面试题:线程池有几种实现方式,线程池的七大参数有哪些?

2021-02-25 11:40发布

昨天参加面试,遇到一个尴尬的问题;我准备了多线程的实现方式,但是面试官问的是:线程池有几种实现方式,线程池的七大参数有哪些?有没有大佬知道的?

昨天参加面试,遇到一个尴尬的问题;我准备了多线程的实现方式,但是面试官问的是:线程池有几种实现方式,线程池的七大参数有哪些?有没有大佬知道的?

6条回答
三岁奶猫
2楼 · 2021-02-26 11:14

1.corePoolSize:线程池中的常驻核心线程数

在创建了线程池后,当有请求任务进来之后,就会安排池中的线程去执行请求任务,近似理解为今日当值线程

当线程池中的线程数目达到corePoolSize后,就会把到达的任务放入缓存队列中。

2.maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1

3.keepAliveTime:多余的空闲线程的存活时间。

当前线程池数量超过corePoolSize时,当空闲时间达到keepAliveTime值时,

多余空闲线程会被销毁直到只剩下corePoolSize个线程为止

默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池找那个的线程数不大于corePoolSize。

4.unit:keepAliveTime的单位

5.workQueue:任务队列,被提交但尚未被执行的任务

6.threadFactory:表示生成线程池中工作线程的线程工厂,用于创建线程一般默认即可

7.handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池最大线程数(maximumPoolSize)时如何处理


猫的想法不敢猜
3楼 · 2021-02-28 12:32

线程池的构造函数有7个参数,分别是corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。五种实现方式

小张同学
4楼 · 2021-03-01 09:58

实现方式一共有四种:

   1.newSingleThreadExecutor:

  • 底层:FinalizableDelegatedExecutorService包装的ThreadPoolExecutor实例,corePoolSize为1;maximumPoolSize为1;keepAliveTime为0L;unit为:TimeUnit.MILLISECONDS;workQueue为:new LinkedBlockingQueue() 无界阻塞队列

  • 通俗:创建只有一个线程的线程池,且线程的存活时间是无限的;当该线程正繁忙时,对于新任务会进入阻塞队列中(无界的阻塞队列)

  • 适用:一个任务一个任务执行的场景

   2.newCachedThreadPool

  • 底层:返回ThreadPoolExecutor实例,corePoolSize为0;maximumPoolSize为Integer.MAX_VALUE;keepAliveTime为60L;unit为TimeUnit.SECONDS;workQueue为SynchronousQueue(同步队列)

  • 通俗:当有新任务到来,则插入到SynchronousQueue中,由于SynchronousQueue是同步队列,因此会在池中寻找可用线程来执行,若有可以线程则执行,若没有可用线程则创建一个线程来执行该任务;若池中线程空闲时间超过指定大小,则该线程会被销毁。

  • 适用:执行很多短期异步的场景

   3.newFixedThreadPool

  • 底层:返回ThreadPoolExecutor实例,接收参数为所设定线程数量nThread,corePoolSize为nThread,maximumPoolSize为nThread;keepAliveTime为0L(不限时);unit为:TimeUnit.MILLISECONDS;WorkQueue为:new LinkedBlockingQueue() 无界阻塞队列

  • 通俗:创建可容纳固定数量线程的池子,每隔线程的存活时间是无限的,当池子满了就不在添加线程了;如果池中的所有线程均在繁忙状态,对于新任务会进入阻塞队列中(无界的阻塞队列),但是,在线程池空闲时,即线程池中没有可运行任务时,它不会释放工作线程,还会占用一定的系统资源。

  • 适用:长期执行的场景

   4.NewScheduledThreadPool:

  • 底层:创建ScheduledThreadPoolExecutor实例,corePoolSize为传递来的参数,maximumPoolSize为Integer.MAX_VALUE;keepAliveTime为0;unit为:TimeUnit.NANOSECONDS;workQueue为:new DelayedWorkQueue() 一个按超时时间升序排序的队列

  • 通俗:创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构

  • 适用:周期性执行的场景

    七大参数


  • corePoolSize 线程池核心线程大小

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

  • maximumPoolSize 线程池最大线程数量

    一个任务被提交到线程池以后,首先会找有没有空闲存活线程,如果有则直接将任务交给这个空闲线程来执行,如果没有则会缓存到工作队列(后面会介绍)中,如果工作队列满了,才会创建一个新线程,然后从工作队列的头部取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列尾部。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。

  • keepAliveTime 空闲线程存活时间

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

  • unit 空闲线程存活时间单位

    keepAliveTime的计量单位

  • workQueue 工作队列

    新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。jdk中提供了四种工作队列:

    ①ArrayBlockingQueue

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

    ②LinkedBlockingQuene

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

    ③SynchronousQuene

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

    ④PriorityBlockingQueue

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

  • handler 拒绝策略

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

    ①CallerRunsPolicy

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

    ②AbortPolicy

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

    ③DiscardPolicy

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

    ④DiscardOldestPolicy

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


武新雨 - 一个很酷的人。
5楼 · 2021-03-01 10:50

线程池的实现方式是通过Executors类创建几种不同的线程池,常用的话有四种,分别说一下吧


    1.newFixedThreadPool (固定数目线程的线程池)

    2.newCachedThreadPool(可缓存线程的线程池)

    3.newSingleThreadExecutor(单线程的线程池)

    4.newScheduledThreadPool(定时及周期执行的线程池)


常见的参数有:

    corePoolSize:核心线程数

    就是说当线程数小于核心线程数时,即使有线程空闲,线程池会优先创建新线程处理。


    queueCapacity:任务队列容量(阻塞队列)

    当核心线程数达到最大时,新任务会放在队列中排队等待执行


    maxPoolSize:最大线程数

    当线程数 >= corePoolSize,且任务队列已满时,线程池会创建新的线程来处理任务。

    当线程数 = maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常

    

    keepAliveTime:线程空闲时间

    当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量 = corePoolSize


    unit:空闲线程存活时间单位

    keepAliveTime的计量单位


    workQueue:工作队列

    新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。jdk中提供了四种工作队列:

    

        ①ArrayBlockingQueue

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


        ②LinkedBlockingQuene

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


        ③SynchronousQuene

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


        ④PriorityBlockingQueue

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


    threadFactory :线程工厂

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


    handler :拒绝策略

    AbortPolicy(抛出一个异常,默认的) 

    DiscardPolicy(直接丢弃任务) 

    DiscardOldestPolicy(丢弃队列里最老的任务,将当前这个任务继续提 交给线程池) 

    CallerRunsPolicy(交给线程池调用所在的线程进行处理)





希希
6楼 · 2021-03-09 15:23

线程池的构造函数有7个参数,分别是corePoolSize、maximumPoolSize、keepAliveTime、unit、workQueue、threadFactory、handler。五种实现方式

嘿呦嘿呦拔萝卜
7楼 · 2021-03-26 17:21

昨天参加面试,遇到一个尴尬的问题;我准备了多线程的实现方式,但是面试官问的是:线程池有几种实现方式,线程池的七大参数有哪些?有没有大佬知道的?


相关问题推荐

  • 回答 20

    100-199 用于指定客户端应相应的某些动作。 200-299 用于表示请求成功。 300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。 400-499 用于指出客户端的错误。 400 语义有误,当前请求无法被服务器理解。 401 当前请求需要用户验证...

  • 回答 5
    已采纳

    1、相同点(1)都是表现层框架,都是基于MVC设计模型(2)底层都离不开 Servlet API(3)处理请求的机制都是一个核心控制器2、不同点(1)SpringMVC的入口是Servlet,而Struts2的入口是Filter(2)SpringMVC是基于方法设计的,而Struts2是基于类(3)SpringMV...

  • 回答 22
    已采纳

    类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结...

  • 回答 23
    已采纳

    (1)idea启动时会有两个快捷方式,安装完后默认生成在桌面的是32位的idea的快捷方式,如果我们使用这个快捷方式运行大项目,一般都会很卡。解决方法是找到idea的安装目录,然后进入bin文件夹,找到名称为idea64的应用程序,右键他生成桌面快捷方式。以后每次...

  • 回答 12
    已采纳

    获取Map集合中所有的key可以通过map集合的keySet()方法获取例如:    Map map = new HashMap();    map.put(xx,xx); //存放数据    //.... 省略    Set set = map.keySet();    //可以通过迭代器进行测试    Iterator iter = set.iter...

  • 回答 4
    已采纳

    Java中有八种数据类型,基础数据类型分别是:byte,short,int,long,float,double,char,boolean,引用数据类型分别是:数组,类和接口。方法传参的时候我们有两种,一种是形式参数(定义方法时写的参数),一种是实际参数(调用方法时给的具体值)。首先...

  • 回答 15
    已采纳

    现在的架构很多,各种各样的,如高并发架构、异地多活架构、容器化架构、微服务架构、高可用架构、弹性化架构等,还有和这些架构相关的管理型的技术方法,如 DevOps、应用监控、自动化运维、SOA 服务治理、去 IOE 等等,还有很多。分布式架构其实就是分布式系...

  • 回答 10

    1、监控GC的状态使用各种JVM工具,查看当前日志,分析JVM参数的设置,分析堆内存快照和GC日志,根据实际的各区域的内存划分和GC的执行时间,判断是否需要进行优化2、分析结果、判断是否需要优化如果各项参数设置合理,系统没有超时的日志出现,GC频率也不高,...

  • 回答 1

    说个题外话,根本就不该说坏话什么的,做好本职工作最靠谱

  • 回答 2

    面对这样的问题时,首先应懂得扬长避短,但是并不是一板一眼的说自己的缺点,可以将自己的专业提升计划描述一下,让面试官认为自我是有职业规划和上进心。

  • 回答 2

    实打实的说,其实培训出来的是为了更能贴合企业的需求,掌握技能要求,是否参加培训个人的权利,考官一般不会抵触,培训不是为了应对面试,是为了能更好的复合企业的用人要求。平常心态去看这件事,因为现在培训已经成为主流了,大学学习的都是理论型的知识,...

  • 回答 3

    一、 工作内容,如果工作主要是打杂,给钱多也要慎重,这没进步;二、 部门情况,部门是否受重视,有多少部门人员,有没有业内大牛,这也是重要的成长环境诉求;三、 公司发展,有锅里的,才能有碗里的,公司有发展个人才能有机会。...

  • 回答 6

    可以接受加班,但我一般都不会加班,因为我能够在白天的时间里把该做的事情都全部做完。

  • 回答 3

    我个人一般会问,如果我在贵公司任职,我的职业发展会有哪些可能呢

  • 回答 9

    一、为什么会离职? 二、为什么会选择xx公司? 三、为什么选择这个职位? 四、在原来的单位主要做什么工作的? 五、在原来工作上有哪些创新? 六、原来工作上遭遇了哪些挫折? 七、在工作中你联系最紧密的关系单位是哪里?为什么? 八、在这个新平台上...

  • 回答 4

    安静不被打扰的环境是必须的,电话面试一般会持续二十分钟以上,同时要保持精神高度集中,如果是HR的面试,更多的会考量候选人的求职动机,职位匹配度,性格等。用人部门会注重专业能力的考察 。简历主要有两部分:第一部分是个人介绍、联系方式、工作经历。...

没有解决我的问题,去提问