具有许多阻塞任务的线程池

3
我正在使用一个线程池,它应该能够执行数百个并发任务。然而,这些任务通常很少进行计算,并且大部分时间都在等待某些服务器响应。因此,如果线程池大小包含数百个线程,只有其中的一些线程会处于活动状态,而大部分线程将处于等待状态。
我知道这通常不是线程池使用的好习惯,但当前的设计不允许使我的任务异步化,以便它们可以在等待服务器响应时返回控制权。因此,鉴于这种限制,我认为我的最大问题是线程堆栈空间的内存消耗增加。
那么,有没有办法使用某种轻量级线程来减少内存消耗?
我现在知道有一个JVM选项-Xss来控制堆栈内存,但似乎没有办法仅针对线程池或线程进行控制,而不是为VM中所有线程进行更改,对吗?
此外,您有任何关于解决我的问题的更好建议吗?

据我所知,这些线程执行网络通信? - Marcio Aguiar
是的,但不幸的是我没有通信层的低级控制。 - Lobachevsky
只是一点提示:如果线程总数确实是一个问题,缓存的线程池似乎非常适合您的用例。缓存将允许在线程活动激增时进行良好的线程重用,并且生存时间将允许它们在给定时间后停止(从而释放资源)。这将缓解问题(如果您确实有一个问题,例如,在典型的当前硬件上,1000个线程完全没有问题)。 - GPI
2个回答

4
我知道通常这不是线程池使用的好方法。
我不同意。我认为这是一个完美的做法。你是否遇到了这种方法的问题?否则,从标准线程切换似乎对我来说是过早优化。
那么有没有一种使用不会消耗太多内存的轻量级线程的方法?
我认为你已经在使用了。线程已经相对轻量级了,除非你在使用非常受限制的JVM,否则我认为没有理由担心数百个线程。
此外,你有关于更好的解决方案的建议吗?
我所看到的任何解决方案都将更加复杂,并且再次成为过早优化的定义。例如,你可以使用NIO并在服务器响应可用时自己调度线程,但这是使用线程可以免费获得的东西。

我不同意。我认为这是一种完美的实践。你是否认为这种方法存在问题,因为这对我来说似乎有点过早优化了? - Lobachevsky
我还没有观察到任何真正的问题,但通常情况下我的线程池大约有500个线程,只有一个或两个线程在活动。现在我需要增加我的线程池限制,可能超过1000,所以我担心内存开销。 - Lobachevsky
你可以通过点击X @Kostadin来删除该评论。如果您发现内存问题或者怀疑出现了抖动,那么我建议您及时处理。一个好的分析器也会告诉您是否存在问题。在我的测试中,我创建了2k个线程,占用不到3MB的内存,因此线程数量不应该是一个问题。 - Gray
另外,我需要使用的库目前不支持NIO,所以很遗憾我无法实现自己的调度。 - Lobachevsky
谢谢,Gray。我会继续进行一些测试。 - Lobachevsky

2
有没有一种轻量级的线程可以使用,不会占用太多内存呢?
在线程池中使用普通线程可能足够轻量级了。
我知道有一个JVM选项-Xss来控制堆栈内存,但似乎没有办法仅针对线程池或线程进行控制,而不是为VM中的所有线程进行更改,对吗?
这是每个线程的最大大小。这是你想要获得StackOverFlowError而不是继续运行的大小。在我看来,按线程基础进行调整几乎没有好处。
线程堆栈使用主内存来存储实际使用的部分和虚拟内存来存储其余部分。如果您拥有64位JVM,则虚拟内存很便宜。如果这是一个问题,我会切换到64位。
另外,您是否有任何更好的解决方案建议?
如果您有数千个线程,可以考虑使用非阻塞IO。听起来您不需要担心。在我的测试中,如果线程不做其他事情,拥有10,000个活动线程将消耗一个CPU。每百个线程,您可能浪费1%的一个CPU。如果您有多余的CPU,这不太可能成为问题。

好的,那我会增加线程池大小并运行一些测试,看是否出现任何问题。我没有注意到 -Xss 只是最大大小。那应该没问题了。 - Lobachevsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接