线程池合理配置线程数

线程切换

  1. CPU给线程分配时间片(也就是分配给线程的时间),执行完时间片后会切换到另一个线程。
  2. 切换之前会保存线程的状态,下次时间片再给这个线程时才能知道当前状态。
  3. 从保存线程A的状态再到切换到线程B时,重新加载线程B的状态的这个过程就叫上下文切换。
  4. 而上下切换时会消耗大量的CPU时间。

CPU运行状态分为用户态和内核态。 线程切换状态会使CPU运行状态从用户态转换到内核态。如果切换内存状态,需要先把本线程的代码和变量写入内存。

线程开销

  1. 上下文切换消耗
  2. 线程创建和消亡的开销
  3. 线程需要保存维持线程本地栈,会消耗内存

对于内存而言,堆内存、代码区一般属于一个进程,但是栈却是属于一个线程的,且每个线程拥有一个独立的栈。

线程池合理配置线程数

  1. CPU密集型 
    CPU密集型的意思就是该任务需要大量运算,而没有阻塞,CPU一直全速运行。 
    CPU密集型任务只有在真正的多核CPU上才可能得到加速(通过多线程)。 
    CPU密集型任务配置尽可能少的线程数,开太多线程反而会因为线程切换时切换上下文而浪费资源。 
    CPU密集型线程数配置公式:CPU核数+1个线程的线程池

  2. IO密集型 
    IO密集型,即该任务需要大量的IO,即大量的阻塞,比如磁盘IO(读取文件)和网络IO(网络请求)。 
    在单线程上运行IO密集型任务会导致浪费大量的CPU运算能力浪费在等待。 
    因为IO操作会阻塞线程,CPU利用率不高,可以开多点线程,阻塞时可以切换到其他就绪线程,提高CPU利用率。 
    所以IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要利用了被浪费掉的阻塞时间。 
    2.1 第一种配置方式: 
    由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程。 
    配置公式(市场一般用这种):CPU核数 * 2。 
    2.2 第二种配置方式: 
    IO密集型时,大部分线程都阻塞,故需要多配置线程数。 
    配置公式:CPU核数 / 1 – 阻塞系数(0.8~0.9之间) 
    比如:8核 / (1 – 0.9) = 80个线程数

代码获取核数

// 可以的处理器
Runtime.getRuntime().availableProcessors()
posted @ 2019-09-29 18:59  要好好吃饭  阅读(837)  评论(0编辑  收藏  举报