Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 切换线程时是什么导致多线程程序挂起的?_Java_Multithreading - Fatal编程技术网

Java 切换线程时是什么导致多线程程序挂起的?

Java 切换线程时是什么导致多线程程序挂起的?,java,multithreading,Java,Multithreading,我有一个多线程程序,它的线程数可以自定义。该程序负责生成HTTP请求,将请求发送到web服务,接收响应并解析响应以获得一些结果值 由于每个请求获得响应几乎需要1秒,为了使程序获得尽可能多的响应,启动了多个线程 以下代码用于启动多线程: 。。。 对于(int i=0;i

我有一个多线程程序,它的线程数可以自定义。该程序负责生成HTTP请求,将请求发送到web服务,接收响应并解析响应以获得一些结果值

由于每个请求获得响应几乎需要1秒,为了使程序获得尽可能多的响应,启动了多个线程

以下代码用于启动多线程:

。。。
对于(int i=0;i

当线程数为50时,总共生成并发送了10K个请求,程序运行良好。当线程数仍然为50,且总请求数为100K时。发送95K+请求时,程序挂起。没有例外,程序就挂在那里

然后我添加了一些JVM参数,如:java-Xmx1024M-Xms512M-XX:MaxPermSize=256m。。。有了这样的参数,每100K请求就有50个线程工作。然而,50个线程/1M请求再次挂起。我将线程编号设置为20,请求编号设置为1M,它再次工作

我想将线程数设置为50,因为在使用较少的请求数(10K)进行测试时,50个线程的效率最高。请求数量可以大得多,如10米、100米、事件1B。在这种情况下,增加-Xmx-Xms或MaxPermSize的大小不是一个好主意。我该怎么办?程序挂起的根本原因是什么

===========================================================

我使用Executor服务而不是直接使用线程。但问题也出现了。我重新检查了代码,发现有一个错误:我为每个请求实例化了一个HttpClient对象。我更改了代码,为每个线程实例化了一个HttpClient实例,程序不再挂起


我认为程序挂起的根本原因是它设置了太多到web服务的HTTP连接,并耗尽了web服务的所有线程。这使得web服务无法响应任何新到达的请求。对吗

仅从这些信息很难判断,但从堆设置会影响结果这一事实来看,我打赌内容生成和内容解析(存储)之间的调度很差

在这种应用程序中,一种常见的情况是,生成内容的线程比获取并存储内容的线程生成的速度更快。这将逐渐增加用于在内存中保存内容的堆内存量,在某个时候吞吐量将开始下降

首先要做的是通过附加一个堆查看器(如VisualVM)来确认这一假设。如果堆使用率逐渐增加,并开始保持在较高的水平,而吞吐量降低,这很可能是罪魁祸首(您还可以确认内存中的内容确实是生成的内容)

通常,瓶颈是用于存储内容的持久层的IO。根据代码所做的工作,解析代码(或其他地方)中可能会出现CPU瓶颈,但这种情况通常很少见


对于这种情况,最常见的补救方法是使用有界队列使生成进程等待解析(存储)进程赶上。看看这个答案:。您必须了解线程池,但它确实比原始线程有了巨大的改进,而且它是处理此类问题的最干净的方法

+1所有使用建议

您还提到您正在使用Http客户端。很少有配置参数会影响性能


关于程序挂起。它可能是大型垃圾收集器运行的死锁。我相信类似的工具,可以帮助你调试这两种情况。

< p>因为我们不知道线程挂在哪里:你是否考虑过某种线程监视,使用线程分析器或使用thRexMxBeB获得线程的周期堆栈跟踪?
正如其他一些海报所提到的,对于任何可伸缩性问题,您也应该关注gc.log。观察你的记忆足迹。但这可能不是问题所在,因为即使是完整的gc最终也应该完成,而您的程序不会。

您所说的“挂起”是什么意思?你是说绞刑吗?有许多因素可能会影响这一点,尤其是您连接的Web服务器可能具有最大数量的并发连接,这意味着程序中的大多数线程都在等待Web服务器开始与它们对话。使用内置线程池可以让您的生活更轻松,例如,其中一个请求是由提供的,而不是自己管理的(但这可能无法解决您的问题)。您如何发送请求?有多少线程正在发送,多少线程在解析请求?如果你希望你的应用程序扩展到任意的一个请求/请求,也许你可能想考虑使用[线程池](),而不是为每个请求生成一个新线程。是的,它应该是“挂起”而不是“等待”。我已经和web服务开发人员确认过,并确保没有连接限制。如果堆被填满,这不会触发OutOfMemoryError吗?@Jan Dvorak:我不确定它是如何工作的,但我看到应用程序在主要死于“GC开销达到”OOME之前存活了相当长的时间。当堆变得稀少并且在某些情况下可以长时间工作时,JVMGC可能有一些策略可以使用?但我只是在猜测,“嘎嘎嘎嘎”的行为