线程个数到底怎么设置?

线程个数到底怎么设置?,第1张

其实大部分人会说这个问题,傻子才问,实验一下不就知道了。是的实验一下就知道了,但是并不是每个人都愿意动手的。世界上还一种人不傻,但是懒。哥也是其中一员。

之前一直没闹懂cpu核数和线程数的关系什么,我一直以为2核8线程是指:两个物理上的核同时可以处理8个线程。( 这里的同时是绝对意义上的同步处理。 )但是我搜了一下,貌似并不是,之前理解完全错误。

参考:https://zhidao.baidu.com/question/564747175879215284.html

           https://www.cnblogs.com/hitwhhw09/p/4718404.html

最近做个http请求。有点大 几千万次。给我的机器是2核40线程。所以我想啊40线程可以同时处理40个线程,按照网上说的设置2-3倍,让他跑吧。然后我设置了80个,跑了一两天。崩了!带我的那个人更牛逼,直接设置3w个线程。然后觉得慢,就说你去做个试验看看,线程设置多少合适。然后实现数据如下:

connectionTimeOut指http请求超时设置,soTimeOut指等待返回时间超时。我们场景是希望请求获得有效返回。

从试验数据上看,单纯从处理速度,不管suc的话,设置在机器线程数量的10倍左右合适。如果从成功结果上看(抛开超时设置)越接近物理核数设置,请求成功率越高。

具体原因因为大概可以猜到,但是抱着严谨精神,我就不说了(我没查,但是学过计算机组成原理和 *** 作系统,所以大概理解)。希望大家自己去查吧。

尽然数据贴出来了,就结合着数据找点经验吧。抛开 http因素。多核多线程情况下 线程数 设置 为线程数的10倍左右处理速度应该最快。

http请求照顾到成功率情况,request超时设置大点更为合理,根据http 响应服务器来定,我们这个应该2-4s直接合理,response超时设置500足够。线程数量应设置在50-240之间,具体大小应该计算或者再细测获得。

举个去饭店吃饭的例子,假设饭店里只有一个服务员,这个服务员每次只能服务一桌顾客,那么后来的顾客就只能等前面的顾客结束用餐后才能进行就餐,这样导致好多顾客等不及就去了别家。老板为了挽回这种局面,就额外聘请了其他几个服务员。这样一来,每次饭店就能同时服务之前好几倍的客人了。老板看到客流量大大增加,虽然需要另外付出几个服务员的工资,但是相较于总体收入来说,提升的收益远大于付出。这个例子里的服务员其实就相当于一个线程,提供读写、计算能力。在单线程模式下,任务都是串行执行的,前一个任务执行完才能执行下一个任务,简答的说,这种方式的效率很低下,最简单的解决办法就是,找一种方法可以同时执行多个任务,这就是多线程的来源。

既然多线程可以提高任务执行的效率,那么是不是线程数越多,效率提升的越明显呢?同样采用饭店的例子来说,前期可能多请几个服务员会使饭店的收益明显提升,但是想通过继续招聘服务员的方式来持续扩大营业额就会有点不切实际。思考一下:即使招聘了足够多的服务员,每个顾客过来都能有自己的专属服务员,是不是就能提高饭店的产出效率呢?当然不是,即使每个服务员收到了顾客的下单后立即反馈到后厨,后厨的厨师也不一定能马上做好相应的饭菜,做完每一份饭菜也是需要一定时间的。那这种情况下想要提高产出效率就只能再招聘更多的厨师了。这里的厨师其实对应饭店本身的处理能力,也就是我们常说的硬件资源。单纯的通过招聘服务员(提升线程数),受到饭店本身处理能力的限制,其实是不会再对效率有显著的提升。相反,招聘更多的服务员反而会消耗更多的工资。

线程的本质都是在处理一些事情。这些事情按特点可划分为io密集型和CPU密集型。简言之,io密集型程序主要用于io的读写,比如文件的读写;而cpu密集型程序主要用作计算,比如循环、递归等计算处理过程。那么这两种类型的程序应该如何设置线程数才能使效率最大化呢?下面分开叙述:

io密集型程序的主要耗时在相关io的 *** 作上,以阻塞性io为例(这里不展开讲io的类型),io的耗时主要在于数据的准备等待及写入。这个时间相较于cpu的处理时间通常是要更多的。我们设置最优线程数的目的就是希望能够同时处理多个事情,避免相互之间的等待,最好是io处理的线程和cpu处理的线程同时结束就完美了。基于这个考虑,我们可以归纳出一个数学模型:假设io处理的时间为to,cpu处理的时间为tu,io线程数为1,那么基于io和cpu同时处理完成的考虑,cpu的线程数即为to/tu,另外由于cpu可能有多个核心,所以最终合适的线程总数为(1+to/tu)*cpu核心数

cpu密集型程序主要考虑cpu的计算时间,多个核心的线程可并行执行,所以合适的线程数应该为cpu核心数,考虑到线程阻塞等异常情况的影响,可以设定为cpu核心数+1

线程数量不是越多越好,总会有一个较优的值区间,而且这个线程数的设定也不能一概而论,要针对具体的线程类型来考虑,本文基于io密集型和cpu密集型线程分别给出估算最优线程数的思考过程,记录也是为了更好的思考。

-Xms:表示java虚拟机堆区内存初始内存分配的大小,通常为 *** 作系统可用内存的1/64大小即可,但仍需按照实际情况进行分配。

2、-Xmx:表示java虚拟机堆区内存可被分配的最大上限,通常为 *** 作系统可用内存的1/4大小。

开发过程中,通常会将-Xms 与-Xmx两个参数的配置相同的值,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源。

1、-XX:newSize:表示新生代初始内存的大小,应该小于-Xms的值;

2、-XX:MaxnewSize:表示新生代可被分配的内存的最大上限;当然这个值应该小于-Xmx的值;

3、-Xmn:至于这个参数则是对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置,也就是说如果通过-Xmn来配置新生代的内存大小,那么-XX:newSize = -XX:MaxnewSize = -Xmn,虽然会很方便,但需要注意的是这个参数是在JDK1.4版本以后才使用的

-Xmn2g:设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。

4、-Xss128k:设置每个线程的堆栈大小。 JDK5.0以后每个线程堆栈大小为1M,以前每个线程堆栈大小为256K。根据应用的线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更 多的线程。但是 *** 作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。

java虚拟机对非堆区内存配置的两个参数:

1、-XX:PermSize:表示非堆区初始内存分配大小(方法区)

2、-XX:MaxPermSize:表示对非堆区分配的内存的最大上限(方法区)。

在配置之前一定要慎重的考虑一下自身软件所需要的非堆区内存大小,因为此处内存是不会被java垃圾回收机制进行处理的地方。并且更加要注意的是最大堆内存与最大非堆内存的和绝对不能够超出 *** 作系统的可用内存。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/6867521.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-03-29
下一篇 2023-03-29

发表评论

登录后才能评论

评论列表(0条)

保存