繁体   English   中英

为Java RIA客户端应用程序配置线程池的最佳方法

[英]Best way to configure a Threadpool for a Java RIA client app

我有一个Java客户端,它通过HTTP访问我们的服务器端,发出几个小请求来加载每个新的数据页。 我们维护一个线程池来处理所有非UI处理,因此所有后台客户端任务以及所有想要与服务器建立连接的任务。 我一直在研究一些性能问题,但不确定我们是否已尽可能完善线程池。 当前,我们使用核心池大小为8的ThreadPoolExecutor,对工作队列使用LinkedBlockingQueue,因此最大池大小将被忽略。 毫无疑问,在所有情况下都无法简单地做到这一点,但有没有最佳实践。 我目前的想法是

1)我将切换为使用SynchronousQueue而不是LinkedBlockingQueue,以便使池可以增长到最大池大小。 2)我将最大池大小设置为无限制。

基本上,我当前的担心是,由于线程池大小的上限,服务器端偶尔出现的性能问题会导致无关的客户端处理停止。 我担心无止境地管理客户端上的那些线程会带来额外的损失,可能只是两种弊端中的一种。

有什么建议,最佳做法或有用的参考资料吗? 干杯,罗宾

通常,网络延迟很容易比客户端上的内存分配或线程管理方面可能发生的任何事情高几个数量级。 因此,通常来说,如果您遇到性能瓶颈,请首先关注网络链接。

如果问题在于您的服务器根本无法跟上客户端的请求,那么增加客户端的线程数量将无济于事:您只需等待8个线程来获得对更多请求的响应就可以了线程正在等待(由于正在管理的连接数量增加,甚至可能由于增加服务器负载而加剧服务器端问题)。

JDK中的两个并发队列都是高性能的。 选择实际上归结为用法语义。 如果您有非阻塞管道,则使用非阻塞队列更为自然。 如果您不这样做,那么使用阻塞队列更有意义。 (您始终可以将Integer.MAX_VALUE指定为限制)。 如果不需要FIFO处理,请确保您未指定合理的顺序,因为这将对性能造成重大影响。

听起来您可能最好限制队列大小:当有许多请求排队时,您的应用程序是否仍能正常运行(将所有任务长时间排队是否可以接受,对其他任务来说更重要)? 如果仍然有排队的任务并且用户退出应用程序,会发生什么情况? 如果队列变得非常大,那么服务器是否有可能赶上(足够快的时间)完全向用户隐藏问题?

我想为需要更新其用户界面响应的请求创建一个队列,并使其队列保持很小。 如果此队列太大,请通知用户。

对于实际的后台任务,请保留一个单独的池,该池具有更长的队列,但不是无限的。 当该池增长时或当用户想要退出但仍有任务时,为该池定义优美的行为,应该怎么办?

正如alphazero所说,如果您遇到瓶颈,则无论使用哪种方法,客户端等待作业的数量都会继续增长。

真正的问题是您要如何处理瓶颈。 或更正确地说,是您希望用户如何处理瓶颈。

如果使用无限制的队列,则不会收到有关瓶颈已发生的反馈。 在某些应用程序中,这很好:如果用户启动异步任务,则无需报告积压(假定最终清除了该积压)。 但是,如果用户在执行下一个客户端任务之前需要等待响应,这是非常糟糕的。

如果在有界队列上使用LinkedBlockingQueue.offer() ,那么您将立即得到一个响应,指出队列已满,并且可以采取措施,例如禁用某些应用程序功能,弹出对话框等。 但是,这将需要您做更多的工作,特别是如果可以从多个地方提交请求的话。 我建议,如果还没有,请在服务器队列上创建一个GUI感知层,以提供常见的行为。

而且,当然,永远不要从事件线程中调用LinkedBlockingQueue.put() (除非您不介意挂起的客户端)。

为什么不创建无界队列,而是在队列达到一定大小时拒绝任务(甚至可能通知用户服务器正忙(取决于应用程序!))? 然后,您可以记录此事件并找出在服务器端发生了什么事以进行备份。此外,除非您要连接到多个远程服务器,否则池中只有几个线程可能没有什么意义,尽管这确实取决于您的应用程序,它的功能以及与谁交谈。

拥有无限制的池通常很危险,因为它通常不会正常降级。 最好记录问题,发出警报,防止进一步的操作排队,并弄清楚如何扩展服务器端(如果存在问题),以防止再次发生这种情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM