JAVA线程池

为什么使用线程池

  1. 降低资源消耗,提高线程利用率,降低创建和销毁线程的消耗。
  2. 提高响应速度;任务来了,直接有线程可用可执行,而不是先创建线程,在执行。
  3. 提高线程的可管理性,线程是稀缺资源,使用线程可统一分配调优监控

线程池参数

  • corePoolSize代表核心线程数,也就是正常情况创建工作的线程数,这些线程创建后并不会消除,而是一种常驻线程
  • maxinumPoolSize代表最大线程数,它于核心线程数相对应,代表最大允许被创建的线程数,比如当前任务较多,将核心线程数都用完了,还无法满足需求时,此时就会创建新的线程,但是线程池内线总数不会超过最大线程数
  • keepAliveTime、unit表示超过核心线程数之外的线程的空闲存活时间,也就是核心线程不会消除,但是超过核心线程的部分线程如果空闲一定的时间则会被消除,我们可以通过setKeepAliveTime来设置空闲时间
  • workQueue用来存放执行的任务,假设我们现在核心线程已经被使用,还有任务进来则全部放入队列,直到整个队列放满担任务还在持续进入则会开始创建的新的线程
  • ThreadFactory实际上是一个线程工厂,用来生产线程执行任务。我们可以选择使用默认的创建工厂,产生的线程都在同一组内,拥有相同的优先级,且都不是守护线程。当然我们也可以选择自定义线程工厂,一般我们会根据业务来制定不同的线程工厂
  • Handle任务拒绝策略,有两种情况,第一种是当我们调用shutdown等方法关闭线程池后,这时候即使线程池内部还有没有执行玩的任务正在执行,但是由于线程池已经关闭,我们在继续向线程池提交任务就会再到拒绝。另一种情况就是当达到最大线程数,线程池已经没有能力继续提交新的任务时,这时也就拒绝

AbortPolicy:直接抛出异常,默认策略;
CallerRunsPolicy:用调用者所在的线程来执行任务;
DiscardOldestPolicy:丢弃阻塞队列中最老的任务,并执行当前任务;
DiscardPolicy:直接丢弃任务;

线程池处理流程

在这里插入图片描述

线程池中阻塞队列的作用?

一般的队列只能保证作为一个有限长度的缓冲区,如果超出了缓冲长度,就无法保留当前的任务了,阻塞队列通过阻塞可以保留当前想要继续入队的任务。阻塞队列可以保证任务队列中没有任务时阻塞获取任务的线程,使得线程进入wait状态,释放cpu资源。阻塞队列自带阻塞和唤醒的功能,不需要而外处理,无任务执行时,线程池利用阻塞队列的take方法挂起,从而维持核心线程的存活,不至于一直占用cpu资源

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

在创建新线程的时候,是需要获取全局锁的,这时候其它的就得阻塞,影响整体效率。

线程池复用的原理

线程池将线程和任务进行解耦,线程是线程,任务时任务,摆脱了之前通过Thread创建线程时的一个必须对应有一个任务的限制。在线程池中,同一个线程可以从阻塞队列中不断获取新任务来执行,其核心原理在于线程池对Thread进行了封装,并不是每次执行任务都会调用Thread.start()来创建新线程,而是让每个线程去执行一个循环任务,在这个循环任务中不停检查是否有任务需要被执行,也就是调用任务中的run方法,将run方法当成一个普通的方法执行,通过这种方式只使用固定的线程将所有的run方法串联起来。

线程池创建大小

最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1* CPU数目

比如平均每个线程CPU运行时间为0.5s,而线程等待时间(非CPU运行时间,比如IO)为1.5s,CPU核心数为8,那么根据上面这个公式 (1.5/0.5+1)×8=32
一般我们会设置 CPU核数+1 防止由于其他因素导致线程阻塞等。
那么换算过来的话就是(1.5/0.5+1)×(8+1)=36
但是现在计算机cpu都是超线程技术如果是8和的话那么使用超线程技术的话那么就是16核
所以(1.5/0.5+1)×(8×2+1)=68

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员劝退师-TAO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值