关于多线程:在Java J2EE服务器上平衡CPU /内存资源的线程使用

Balancing thread usage of CPU/memory resources on Java J2EE server

我正在开发一个在JBoss上运行的用于文档协作的网站/在线服务。在具有2.5Ghz cpu和2GB RAM的Linux机器上进行测试期间,页面响应非常快,我们正考虑在此机器上启动。

在文档处理过程中出现问题。用户上传文档后,将启动一个新线程,该线程除其他功能外还转换文档,从文档中提取文本和图像,并通过https将其上传到另一台服务器上。用户可以一次上传许多文档,并且用于处理它们的线程可以同时工作。在此处理完成之前,网站几乎没有响应。

您能否给我一些建议,说明如何在处理文档的线程上分配CPU /内存的百分比(例如,最大40%)?如果无法做到这一点,请在方法/模式上为我提供建议,该方法/模式将以某种方式在JBoss响应页面请求和处理文档的线程之间分担机器上的负载。

问候


实际上,没有一种方法可以为给定线程分配一定百分比的CPU /内存时间。您可以降低线程优先级,这样就不会使所有资源饱和:

1
2
3
4
int oldPriority = Thread.currentThread().getPriority();
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
// process your documents here
Thread.currentThread().setPriority(oldPriority);

可能更接近于指定百分比的更好方法是使用具有固定线程数的ExecutorService并通过该线程运行所有文档处理。如果给它提供服务器中处理器数量的一半,那么它将有效地将文档处理限制为服务器CPU时间的50%。您需要一个单例服务来建立这样的线程池:

1
2
int threads = Runtime.getRuntime().availableProcessors() / 2;
ExecutorService service = Executors.newFixedThreadPool(threads);

然后,在您的Web请求中,您可以将实现文档处理的Callable传递给服务,并阻塞直到完成:

1
2
Callable<Result> callable = new DocumentProcessorCallable<Object>(doc);
Result result = service.submit(callable).get();

或者,您可能不希望通过提供传递给service.execute(runnable)Runnable实现来阻止并立即返回。有关更多示例和文档,请参见ExecutorService。


在用户提交了文档之后,您可以将它们全部提交到JMS队列中,在该队列中,只有一个MDB实例正在侦听。因此,文档处理将是串行的,因此仅使用一个线程(仍然可能使用大量CPU)。

如果此解决方案还不够,则可以将远程MDB放置在其他服务器上以处理文档,并从根本上减轻文档处理的负担。这里的好处是,此更改基本上仅是配置更改,不需要重新编译您的应用程序。