为何服务器QPS上不去?Java线程调优权威指南
表7:计算10 000支模拟股票价格历史所需的时间 默认情况下,公共池有 4 个线程(在这个配置了 4 个 CPU 的机器上),所以表中的第 3 行为一般情况。在线程数为 1 和 2 时,这类结果会让性能工程师很不开心:它们看上去很不协调,而当某一项测试出现这样的情况时,最常见的原因是测试错误。这里的原因是 forEach 方法有些奇怪的行为:它使用了一个线程执行语句,还使用了公共池中的线程处理来自 Stream 的数据。即使在第 1 个测试中,公共池也是配置为使用一个线程,总的还是会使用两个线程来计算结果。(因此,使用了 2 个线程的 ThreadPoolExecutor 和使用了 1 个线程的 ForkJoinPool 的耗时基本相同。) 在使用并行 Stream 构造或其他自动并行化特性时,如果需要调整公共池的大小,可以考虑将所需的值减 1。 快速小结 ForkJoinPool 类应该用于递归、分治算法。 应该花些心思来确定,算法中的递归任务何时结束最为合适。创建太多任务会降低性能,但如果任务太少,而任务所需的执行时间又长短不一,也会降低性能。 Java 8 中使用了自动并行化的特性会用到一个公共的 ForkJoinPool 实例。我们可能需要根据实际情况调整这个实例的默认大小。 理解线程如何运作,可以获得很大的性能优势。不过就线程的性能而言,其实没有太多可以调优的:可以修改的 JVM 标志相当少,而且那些标志的效果也很有限。 相反,较好的线程性能是这么来的:遵循管理线程数、限制同步带来的影响的一系列最佳实践原则。借助适当的剖析工具和锁分析工具,可以检查并修改应用,以避免线程和锁的问题给性能带来负面影响。 调节线程栈大小 当空间非常珍贵时,可以调节线程所用的内存。每个线程都有一个原生栈,操作系统用它来保存该线程的调用栈信息(比如,main() 方法调用了 calculate() 方法,而 calculate() 方法又调用了 add() 方法,栈会把这些信息记录下来)。 不同的 JVM 版本,其线程栈的默认大小也有所差别,具体如下所示。一表般而言,如果在 32 位 JVM 上有 128 KB 的栈,在 64 位 JVM 上有 256 KB 的栈,很多应用实际就可以运行了。如果这个值设置得太小,潜在的缺点是,当某个线程的调用栈非常大时,会抛出 StackOverflowError。 几种 JVM 的默认栈大小 (编辑:西安站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |