优化CPU上运行的最大线程数

时间:2013-02-25 17:43:38

标签: java multithreading

想知道什么是决定何时停止在作为线程多次运行同一程序的单核机器上创建新线程的最佳方法?

线程正在获取Web内容并进行一些处理,这意味着每个线程的加载在线程终止之前不会一直保持不变。

我正在考虑有一个监视CPU / RAM负载的线程,如果负载达到某个阈值就停止创建线程,但是如果达到了某些线程数,也停止创建线程,以确保CPU没有超载。

有关实现此目的的技术的任何反馈?

非常感谢, 弗拉基米尔

1 个答案:

答案 0 :(得分:1)

通过监视当前进程使用的CPU来实现这一点很困难。这些数字往往落后于现实,结果将在很大程度上成为高峰和低谷。问题是您的线程大多数将被IO阻塞,并且没有任何好的方法可以预测何时可以在不久的将来读取字节。

也就是说,您可以从某个最大线程数ThreadPoolExecutor开始(对于单个处理器,假设为4),然后每10秒检查一次负载平均值。如果平均负载低于您的要求,那么您可以使用较大的值调用setMaximumPoolSize(...)以在接下来的10秒内增加它。您可能需要在每次计算之间轮询30秒或更长时间以平滑应用程序的性能。

您可以使用以下代码跟踪所有线程的总CPU时间。不确定这是否是最佳方式

    long total = 0;
    for (long id : threadMxBean.getAllThreadIds()) {
        long cpuTime = threadMxBean.getThreadCpuTime(id);
        if (cpuTime > 0) {
            total += cpuTime;
        }
    }
    // since is in nano-seconds
    long currentCpuMillis = total / 1000000;

您可以考虑尝试最大化吞吐量,而不是尝试最大化蜘蛛的CPU级别。获取每单位时间内抓取的页数样本,并增加或减少ExecutorService中的最大线程数,直到最大化为止。

要考虑的一件事是使用NIO和选择器,因此您的线程总是忙,而不是总是等待IO。这是一个good example tutorial about NIO/Selectors。您也可以考虑使用Pyronet,它似乎提供了围绕NIO的一些好的功能。