我的应用程序使用Executor为大量任务提供线程池。通过分析和基准测试,我已经确定当每个核心有多个线程时,我的应用程序运行速度最快。一个很好的启发式法则是从每个核心开始使用4个线程,直到达到>90%的CPU或>90%的RAM。
是否有可用的Executor可以自动处理这个问题?即自动使用N个线程每个核心(不仅仅是一个),或者更理想的是,根据CPU和RAM使用情况限制线程池大小?
如果没有 - 我该如何以编程方式确定核心数?
我的应用程序使用Executor为大量任务提供线程池。通过分析和基准测试,我已经确定当每个核心有多个线程时,我的应用程序运行速度最快。一个很好的启发式法则是从每个核心开始使用4个线程,直到达到>90%的CPU或>90%的RAM。
是否有可用的Executor可以自动处理这个问题?即自动使用N个线程每个核心(不仅仅是一个),或者更理想的是,根据CPU和RAM使用情况限制线程池大小?
如果没有 - 我该如何以编程方式确定核心数?
Runtime.availableProcessors()
Javadoc:
返回 Java 虚拟机可用的处理器数量。这个值在虚拟机调用期间可能会发生变化。因此,对可用处理器数量敏感的应用程序应该定期轮询此属性,并相应地调整资源使用。
public double memUsageRatio() {
Runtime r = Runtime.getRuntime();
return (double) (r.totalMemory() - r.freeMemory()) / r.maxMemory();
}
ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
import java.lang.management.*;
public class CPUUsageCollector implements Runnable {
private final static long INTERVAL = 1000L; // polling interval in ms
private long totalCpuTime = 0L; // total CPU time in millis
private double load = 0d; // average load over the interval
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
boolean stopped = false;
@Override
public void run() {
try {
while (!isStopped()) {
long start = System.currentTimeMillis();
long[] ids = threadMXBean.getAllThreadIds();
long time = 0L;
for (long id: ids) {
long l = threadMXBean.getThreadCpuTime(id);
if (l >= 0L) time += l;
}
long newCpuTime = time / 1000000L;
synchronized(this) {
long oldCpuTime = totalCpuTime;
totalCpuTime = newCpuTime;
// load = CPU time difference / sum of elapsed time for all CPUs
load = (double) (newCpuTime - oldCpuTime) /
(double) (INTERVAL * Runtime.getRuntime().availableProcessors());
}
long sleepTime = INTERVAL - (System.currentTimeMillis() - start);
goToSleep(sleepTime <= 0L ? INTERVAL : sleepTime);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized double getLoad() {
return load;
}
public synchronized void goToSleep(final long time) {
try {
wait(time);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
public synchronized boolean isStopped() {
return stopped;
}
public synchronized void setStopped(final boolean stopped) {
this.stopped = stopped;
}
}