介绍
“我应该创建多少个线程?”。 许多年前,我的一个朋友问我这个问题,然后我按照“ CPU核心数+ 1”的指示给了他答案。 当您在这里阅读时,大多数人都在点头。 不幸的是,我们所有人当时都错了。
现在,如果您的体系结构是基于共享资源模型的,那么我会给出答案,那么您的线程号应为“ CPU核心数量+ 1”,具有更好的吞吐量,但是如果您的体系结构是非共享模型(例如SEDA,ACTOR)那么您可以根据需要创建任意多个线程。
走过
因此,出现了一个问题,为什么这么多的长老继续为我们提供“ CPU核心数+ 1”的准则,因为他们告诉我们线程的上下文切换很繁重,并且会阻碍您的系统可伸缩性。 但是noboday注意到他们所使用的编程或体系结构模型。 因此,如果您仔细阅读,会发现其中大多数描述了实用程序设计或体系结构模型是基于共享资源模型的。
给你几个例子:
1.套接字编程–套接字层被许多请求共享,因此您需要在每个请求之间进行上下文切换。
2.信息提供者系统–大多数客户将连续访问相同的请求
等等…
因此,它们将满足访问同一资源情况的多个请求,因此,由于其系统的一致性要求,系统将需要对该资源添加锁定。 锁争用将发挥作用,因此多线程的上下文关系将非常繁重。
在发现这一有趣的事情之后,我认为其他编程或体系结构模型可以绕过该限制。 因此,如果共享资源模型无法创建更多的Java线程,也许我们可以尝试不共享模型。
因此,幸运的是我有机会创建一个需要较大扩展性的系统,该系统需要以非常快的方式发出大量通知。 因此,我决定继续使用SEDA模型进行试验,并通过我的多通道commonj模式进行利用,当前,如果一台计算机上的Java堆设置为1.5 GB,那么我可以运行最大数量约为600个线程的Java应用程序。
那么,一个Java线程的平均内存消耗大约为512 KB(请参阅: http : //www.javacodegeeks.com/2011/04/erlang-vs-java-memory-architecture.html ),因此几乎有600个线程需要300M内存消耗(包括Java本机和Java堆)。 而且,如果您的系统设计良好,那么300M的使用量将不会增加您的负担。
顺便说一句,在Windows中您不能创建超过1000个线程,因为Windows无法很好地处理线程,但是如果您使用NPTL,则可以在Linux中创建1000个线程。 许多人告诉您,Java无法处理并非100%正确的大型并发作业处理。
有人可能会问线程本身的生命周期交换如何:就绪–可运行–运行–等待。 我想说Java和最新的操作系统已经可以有效地处理它们,如果您具有多核CPU并启用NUMA,则整个性能将得到进一步提高。 因此,至少从一开始就不是您的瓶颈。
当然,创建线程和使线程进入运行阶段是非常繁重的事情,因此请充分利用线程池(jdk:执行程序)
您可以参考: http : //community.jboss.org/people/andy.song/blog/2011/02/22/performance-compare-between-kilim-and-multilane-commj-pattern以了解许多Java线程的功能
结论
将来您将如何回答“我应该创建多少个Java线程?”这个问题。 希望您的回答变为:
1.如果您的架构基于共享资源模型,则您的线程号应为“ CPU核心数+1”,并具有更好的吞吐量
2.如果您的架构是非共享模型(例如SEDA,ACTOR),那么您可以创建所需数量的线程。
参考: 应该创建多少个Java线程? 来自我们的JCG合作伙伴 Andy Song,其歌曲为andy's Stuff博客。
翻译自: https://www.javacodegeeks.com/2012/08/java-threads-how-many-should-i-create.html