CPU核数
-
简介
-
获取方式
//可以算出核数,例如结果为4就是4核 System.out.println(Runtime.getRuntime().availableProcessors());
CPU密集型
-
简介
CPU密集是指该任务需要大量复杂的数学计算、图形处理、科学模拟等,而没有阻塞,CPU会一直全速运行(如while循环)。这些任务涉及大量的计算操作,而相对较少的数据读写。
-
计算公式
最佳线程数 = CPU核数 + 1
-
注意事项
CPU密集任务只有在真正的多核CPU上才可能得到加速(通过多线程),而在单核CPU上,无论开几个模拟的多线程都不可能得到加速,因为CPU总的运算能力就那些,所以对于CPU密集型任务配置尽可能少的线程数量。
IO密集型
-
简介
Web 服务器处理大量并发请求时,可能需要读取和写入大量的数据,如静态文件、数据库记录等。在这个场景中,CPU 等待数据的时间可能较长。
-
计算公式
当线程 A 执行 IO 操作时,另外 R 个线程正好执行完各自的 CPU 计算,这样 CPU 的利用率就达到了 100%
最佳线程数 = CPU 核数 * [ 1 +(I/O 耗时 / CPU 耗时)]
-
经验公式
-
CPU核数 * 2
由于IO密集型任务线程并不是一直在执行任务,则配置尽可能多的线程
-
CPU核数/(1-阻塞系数)(阻塞系数在0.8~0.9之间)
IO密集型时,大部分线程都阻塞,故需要多配制线程数,例如:8核/(1-0.9) = 80个线程数
-
-
注意事项
在单线程上运行IO密集型任务会导致大量的CPU运算能力浪费在等待,所以IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要利用了被浪费掉的阻塞时间
-
小结
对于 I/O 密集型计算场景,I/O 耗时和 CPU 耗时的比值是一个关键参数,这个参数是未知且是动态变化的,实际项目中,我们要基于各种不同场景下的压测来估算这个参数(借助apm工具)。原则还是将硬件的性能发挥到极致,所以压测时,我们需要重点关注 CPU、I/O 设备的利用率和**性能指标(响应时间、吞吐量)**之间的关系。
自定义线程池
-
不允许使用Executors创建
-
案例代码
public static void main(String[] args) { // 自定义线程池 ExecutorService threadPool = new ThreadPoolExecutor(3, 5, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); try { for (int i = 0; i < 10; i++) { threadPool.execute(() -> { System.out.println(Thread.currentThread().getName() + "\t 办理业务"); }); } } catch (Exception e) { e.printStackTrace(); } finally { threadPool.shutdown(); } }