关于线程池

1、线程池原理

      首先,简述线程池的作用:线程池是一种池化技术,用于预先创建并管理一组线程,避免频繁创建和销毁线程的开销,提高性能和响应速度,
      然后,简单带一下线程池的几个关键的配置:核心线程数、最大线程数、空闲存活时间、工作队列、拒绝策略。

简述一下线程池的工作原理
1.默认情况下线程不会预创建,任务提交之后才会创建线程(不过设置 prestartAlCoreThreads 可以预创建核心线程,默认为false,可以设置为true会预创建线程)
2.当核心线程满了之后不会新建线程,而是把任务堆积到工作队列中。
3.如果工作队列放不下了,然后才会新增线程,直至达到最大线程数。
4.如果工作队列满了,然后也已经达到最大线程数了,这时候来任务会执行拒绝策略
5.如果线程空闲时间超过空闲存活时间,并且线程线程数是大于核心线程数的则会销毁线程,直到线程数等于核心线程数(设置allowCoreThreadTimeOut为true 可以回收核心线程,默认为 false)。

2、如何设计线程池的核心线程数

线程池的线程数设置其实是需要看你执行的任务是什么类型的。
任务类型可以分:CPU 密集型任务和 IO密集型任务。
CPU 密集型任务,就好比单纯的数学计算任务,它不会涉及 0 操作,也就是说它可以充分利用 CPU 资源(如果涉及 IO,在进行IO的时候 CPU 是空闲的),不会因为 IO操作被阻塞,因此
不需要很多线程,线程多了上下文开销反而会变多。
根据经验法则,CPU 密集型任务线程数=CPU 核心数*1.5
IO密集型任务,有很多IO操作,例如文件的读取、数据库的读取等等,任务在读取这些数据的时候,是无法利用 CPU的,对应的线程会被阻塞等待 IO读取完成,因此如果任务比较多,就需
要有更多的线程来执行任务,来提高等待 IO时候的 CPU 利用率,
根据经验法则,I/O密集型仟务线程数=CPU 核心数*2+1
注意,实际的最佳线程数还是需要具体应用压测分析的,以上公式仅供参考!!

3、任务拒绝策略

  • AbortPolicy:直接抛出RejectedExecutionException异常,阻止系统正常运行。
  • CallerRunsPolicy:“调用者运行”策略,既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者,从而降低新任务的流量。
  • DiscardOldestPolicy:抛弃队列中最旧的任务,尝试为当前提交的任务腾出空间。
  • DiscardPolicy:直接丢弃无法处理的任务,不抛异常。

自定义实现任务拒绝策略

public class Animal implements RejectedExecutionHandler{

    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        
    }
}

4、JAVA并发库中提供的线程池和区别

  • newFixedThreadPool:创建一个固定大小的线程池,线程数量固定,不会自动增长或缩小。(可能出现OOM的情况,任务不断的进行排队,不建议使用

  • newCachedThreadPool:创建一个可缓存的线程池,如果线程池中的线程数量超过了任务数量,那么多余的线程会被回收;如果线程池中的线程数量不足,那么会创建新的线程来执行任务。
    
    (这个线程池核心线程数是0,最大线程数看作无限大,且然后任务队列 SynchronousQueue 是没有存储空间的,每个插入操作必须等待一个删除操作。简单理解就是来个任务就必须找个线程接着,不然就阻塞了,cached 意思就是会缓存之前执行过的线程,缓存时间是 60 秒,这个时候如果有任务进来就可以用之前的线程来执行,所以它适合用在短时间内有大量短任务的场景。如果暂无可用线程,那么来个任务就会新启一个线程去执行这个任务,快速响应任务。但是如果任务的时间很长,那存在的线程就很多,上下文切换就很频繁,切换的消耗就很明显,并且存在太多线程在内存中,也有 OOM 的风险。

  • newSingleThreadExecutor:创建一个单线程的线程池,只有一个线程在执行任务。(无界队列,保证任务顺序执行)

  • newScheduledThreadPool:创建一个支持定时任务的线程池,可以在指定的时间间隔后执行任务。

(用于需要定时或周期性执行任务的场景,底层使用 DelavedWorkQueue 实现延时任务)

  • newWorkStealingPool: Java 8 中引入的一个新的线程池,用于并行执行任务。它的特点是可以自动分配任务到不同的线程中,从而提高程序的并发性和性能。(返回ForkJoinPool)
       (它的工作原理是将任务分配到不同的线程中,每个线程都有自己的任务队列。当一个线程完成一个任务后,它会从其他线程的任务队列中窃取一个任务来执行,从而避免了线程空闲的情况。这种方式可以有效地利用多核处理器的性能,提高程序的执行效率。
       不过需要注意的是,使用newWorkStealingPool时需要谨慎,因为它可能会导致任务的执行顺序不确定,从而影响程序的正确性。因此,在使用它时需要仔细考虑任务的依赖关系和执行顺序,以确保程序的正确性)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值