线程池面试

对线程池的了解?

答:java.util.concurrent.ThreadPoolExecutor类就是一个线程池。客户端调用ThreadPoolExecutor.submit(Runable task)提交任务,线程池内部维护的工作者线程的数量就是该线程池的大小。

为什么使用线程池?

1.降低资源消耗,提高线程的利用率,降低线程创建和销毁过程的消耗。

2.提高响应速度,任务来了,直接有线程可用,而不是创建线程,在执行。

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

解释下线程池的参数?

1.CorePoolSize:代表核心线程数,也就是正常情况下创建工作的线程数,这些线程创建后并不会消除,而是一种常驻线程,随着线程池的消亡而消除。

2.MaxinumPoolSize:代表最大线程数,他与核心线程数相对应,表示最大可允许被创建的线程数,比如当任务较多时,将核心线程数用完了,还无法满足需求是,此时就会创建新的线程,但线程池内线程总数不会超过最大线程数

3.KeepAliveTime、unit:表示超出核心线程数之外的线程空闲存活时间,也就是核心线程不会消除,但超出核心线程数之外的部分线程如果空闲一定的时间会被消除,我们可以通过SetKeepAliveTime来设置空闲时间。

4.WorkQueue:表示用来存放待执行的任务,假设我们的核心线程数用完了,还有任务进来则全部放到等待队列,知道整个队列放满但任务还在持续进入则会开始创建新的线程。

解释:假如核心线程数是 5 ,等待队列是 10,最大线程数是 10,当核心线程数全部在运行,此时队列也存满了等待执行的 10 个任务,此时来了第 11 个需要执行的任务,在这时就要创建第 6个线程。

5.Handler:任务拒绝策略,有两种情况,第一种当我们调用ShutDown等方法关闭线程池后这时候即使线程池内部还有没执行完的任务正在执行,但是由于线程池已经关闭,我们再继续向线程池提交任务就会遭到拒绝,令一种情况是,就是达到最大线程数,线程已经没有能力处理新提交的任务时,这是也拒绝。

解释:当核心线程数,最大线程数,队列都已经满了,来了需要执行的第 21 个任务时,需要执行任务拒绝策略

6.ThreadFactory:实际上是一个线程工厂,用来生产现成的执行任务,我们可以使用默认的创建线程工厂,产生的线程都在一个组中,拥有相同的优先级,且都不是守护线程,我们也可以选择自定义的线程工厂,一般我们会根据业务来制定不同的线程工厂,它其实是一个床架线程的接口,只有一个实现创建线程的方法。

 

线程池的处理流程

线程池执行任务——>核心线程数是否已满,未满创建核心贤臣执行,已满——>任务队列是否已满,未满,将任务放到队列,等待核心线程,核心线程执行完来队列取任务,已满——>最大线程数是否已满,未满创建临时线程,临时线程空闲设置KeepAliveTime,没有执行完从队列中取任务执行,已满——>拒绝策略处理。

 线程池中为什么使用阻塞队列而不适用普通队列?阻塞队列的作用?为什么先添加队列而不是先创建最大线程?

1.为什么使用阻塞队列而不是普通队列?

一般队列只能保证作为一个有限长度的缓冲区,如果超出缓冲长度就无法保留当前来的任务,阻塞队列通过阻塞可以保留当前想要继续入队的任务。

2.阻塞队列的作用?

阻塞队列可以保证任务队列中没有任务时,阻塞获取任务的线程,使线程进入wait状态,释放cpu资源。

阻塞队列自带唤醒和阻塞功能,不需要额外处理,无任务时线程利用阻塞队列的take方法挂起,从而维持核心线程存活不至于一直占用cpu资源。

3.为什么先添加队列而不是先创建线程?

再创建线程时,是要获取全局锁,这时候其他的就要阻塞,影响整体效率。

例如:就好比一个企业里面有 10 个正式名额(core),最多招10个正式员工,要是任务超过正式工人数(task>core)的情况下,工厂领导(线程池)首先不是扩招,而是积压任务,即先放入队列。10个员工慢慢干,如果任务继续增加超过员工极限(队列满了)就要找外包公司帮忙(临时线程),如果正式员工加外包公司还是完成不了,那新来的任务会被领导拒绝(线程池的拒绝策略)

线程池的复用原理?

线程池将线程和任务进行解耦,线程就是线程,任务就是任务,摆脱之前通过Thread创建线程时一个线程必须对应一个任务的限制,

在线程池中,同一个线程可以从阻塞队列中不断获取新任务来执行,其核心原理在于线程池对Thread进行封装,并不是每次执行任务都会调用Thread.Star()来创建线程,而是让每一个线程去执行一个“循环任务”,在这个循环任务中不停检查是否有任务需要被执行,如果有直接被执行,也就是调用线程中的Run()方法,将Run()方法当成一个普通的方法执行,通过这种方法只是用固定的线程就能将所有的run()方法串取出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值