提升–01—线程基础知识–程序、进程、线程–线程池中的线程数量设置多少合适?

提升–01—线程基础知识–程序、进程、线程–线程池中的线程数量设置多少合适?线程基础知识 最大线程数设置多少合适

大家好,欢迎来到IT知识分享网。

线程的历史

  • 之前的硬件,只有一个CPU
  • 之前的OS,只运行一个进程
  • 随着多核CPU的出现,人们开始追求对CPU效率的极致压榨
  • 多线程的程序随之诞生,但随之诞生的,也是非常难以应对的各种并发bug

在这里插入图片描述

进程 线程

多线程–01–程序、进程、线程
纤程/协程:绿色线程,用户管理的(而不是OS管理的)线程

在这里插入图片描述
在这里插入图片描述

– 什么是进程:资源分配的基本单位(静态概念)

– 什么是线程:资源调度的基本单位(动态概念)

– 通俗说:一个程序中不同的执行路径

在这里插入图片描述

在这里插入图片描述

线程的调度,切换线程也存在性能损耗

在这里插入图片描述

区分:

  • 程序:可执行文件,如xx.exe
  • 进程:资源分配的最小单位。一个程序可能由多个进程组成,进程启动后,操作系统会在内存中给进程分配空间
  • 线程:程序调度执行的最小单位,多个线程共享进程中的资源
  • 单线程:只有一条执行路径,一个执行任务
  • 多线程:有多条执行路径在同时运行,多个执行任务

一个java应用程序

一个java应用程序java.exe ,其实至少有三个线程:当然如果发生异常,会影响主线程

  • main线程
  • gc()垃圾回收线程
  • 异常处理线程
一个多线程程序一个进程,会先运行主线程,然后运行期间,再进行线程的切换,抢夺时间片.

1. 单核CPU设定多线程是否有意义

回答这个问题需要考虑,我们的线程被用来执行什么样的任务? 常见的任务分为两种:

  • CPU密集型任务
  • IO密集型任务

CPU密集型任务(CPU-bound):

  • 在一个任务中,主要做计算,CPU持续在运行,CPU利用率高,具有这种特点的任务称为CPU密集型任务。

IO密集型任务(IO-bound):

  • 在一个任务中,大部分时间在进行I/O操作,由于I/O速度远远小于CPU,所以任务的大部分时间都在等待IO,CPU利用率低,具有这种特点的任务称为IO密集型任务。
因为存在线程等待的情况,所以在等待的时间,即是是单核cpu,也可以进行线程切换,让其他线程继续用cpu,这样提高了cpu的利用率.

2. 工作线程数是不是设置的越大越好?

案例:

  • 测试设备:AMD r7 4700u , 8核

需求 :求一个亿的随机数据累加的和.

public class T01_MultiVSSingle_ContextSwitch { 
    //=====================一亿数据累积求和 ============================== private static double[] nums = new double[1_0000_0000]; private static Random r = new Random(); private static DecimalFormat df = new DecimalFormat("0.00"); static { 
    for (int i = 0; i < nums.length; i++) { 
    nums[i] = r.nextDouble(); } } public static void main(String[] args) throws Exception { 
    m1(); m2(); m3(); } } 

单线程方法: m1

 private static void m1() { 
    long start = System.currentTimeMillis(); double result = 0.0; for (int i = 0; i < nums.length; i++) { 
    result += nums[i]; } long end = System.currentTimeMillis(); System.out.println("m1: 1个线程" + (end - start) + " result = " + df.format(result)); } 

2个线程 方法: m2

 static double result1 = 0.0, result2 = 0.0, result = 0.0; private static void m2() throws Exception { 
    Thread t1 = new Thread(() -> { 
    for (int i = 0; i < nums.length / 2; i++) { 
    result1 += nums[i]; } }); Thread t2 = new Thread(() -> { 
    for (int i = nums.length / 2; i < nums.length; i++) { 
    result2 += nums[i]; } }); long start = System.currentTimeMillis(); t1.start(); t2.start(); t1.join(); t2.join(); result = result1 + result2; long end = System.currentTimeMillis(); System.out.println("m2: 2个线程" + (end - start) + " result = " + df.format(result)); } 

32个线程 方法: m3

 private static void m3() throws Exception { 
    final int threadCount = 32; Thread[] threads = new Thread[threadCount]; double[] results = new double[threadCount]; final int segmentCount = nums.length / threadCount; CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { 
    int m = i; threads[i] = new Thread(() -> { 
    for (int j = m * segmentCount; j < (m + 1) * segmentCount && j < nums.length; j++) { 
    results[m] += nums[j]; } latch.countDown(); }); } double resultM3 = 0.0; long start = System.currentTimeMillis(); for (Thread t : threads) { 
    t.start(); } latch.await(); for (int i = 0; i < results.length; i++) { 
    resultM3 += results[i]; } long end = System.currentTimeMillis(); System.out.println("m3: 32个线程" + (end - start) + " result = " + df.format(result)); } 

测试:

在这里插入图片描述

结论:

  • 多线程通常情况下比单线程效率高
  • 线程并不是越多越好,因为线程切换也需要耗费系统资源和时间.

3. 线程池中的线程数量设置多少合适?

在这里插入图片描述

根据任务类型推断:

当我们需要初始化一个线程池时,就要考虑我们的线程池被用来执行什么样的任务。

所以我们在设计线程池时,应先对执行的任务有个大体分类,然后根据类型进行设置。一般而言,两种任务的线程数设置如下:

CPU密集型任务:

  • 线程个数为CPU核数。这几个线程可以并行执行,不存在线程切换到开销,提高了cpu的利用率的同时也减少了切换线程导致的性能损耗

IO密集型任务:

  • 线程个数为CPU核数的两倍。到其中的线程在IO操作的时候,其他线程可以继续用cpu,提高了cpu的利用率

合适线程计算公式:

在这里插入图片描述

实际的w/c等待时间和计算时间的比率,需要实际生产压测出来.运用相关检测工具.
性能分析工具 profile
不管哪种公式和什么类型的任务,都需要实际生产压测数据为参考.

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/128769.html

(0)
上一篇 2025-08-29 14:45
下一篇 2025-08-29 15:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信