Java执行器,根据CPU和RAM使用情况调整线程池
我的应用程序使用执行器为大量任务提供线程池。我通过分析和基准测试确定,当每个核心有多个线程时,我的应用程序运行得最快。一个好的启发式方法是从每个核心4个线程开始,直到达到>90%的CPU或>90%的RAM 是否有现成的执行人来执行?或者每个内核自动使用N个线程(而不仅仅是一个),或者,理想情况下,根据CPU和RAM的使用限制线程池的大小 失败-我如何通过编程确定内核的数量Java执行器,根据CPU和RAM使用情况调整线程池,java,multithreading,concurrency,java.util.concurrent,Java,Multithreading,Concurrency,Java.util.concurrent,我的应用程序使用执行器为大量任务提供线程池。我通过分析和基准测试确定,当每个核心有多个线程时,我的应用程序运行得最快。一个好的启发式方法是从每个核心4个线程开始,直到达到>90%的CPU或>90%的RAM 是否有现成的执行人来执行?或者每个内核自动使用N个线程(而不仅仅是一个),或者,理想情况下,根据CPU和RAM的使用限制线程池的大小 失败-我如何通过编程确定内核的数量 Runtime.availableProcessors() Javadoc: 返回Java虚拟机可用的处理器数。 此值可能
Runtime.availableProcessors()
Javadoc:
返回Java虚拟机可用的处理器数。
此值可能在虚拟机的特定调用期间更改。因此,对可用处理器数量敏感的应用程序应偶尔轮询此属性并适当调整其资源使用情况
一种方法是使用1,起始值为4,然后根据内存和CPU使用情况动态调整最大池大小 更大的问题,imho,是如何测量内存使用和CPU负载。内存使用非常简单:
public double memUsageRatio() {
Runtime r = Runtime.getRuntime();
return (double) (r.totalMemory() - r.freeMemory()) / r.maxMemory();
}
对于CPU负载,问题可能更大,这取决于您运行的平台。在Linux上,您可以使用:
ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage();
这将返回最后一分钟的系统平均负载。不幸的是,在Windows上,此方法总是返回-1。在过去,我将其替换为给定时间间隔内的系统平均负载近似值,计算所有线程的CPU时间之和除以所有处理器的所有运行时间之和。这只是一个近似值,但在大多数情况下效果相当好:
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;
}
}
导入java.lang.management.*;
公共类CPUUsageCollector实现可运行{
私有最终静态长间隔=1000L;//轮询间隔(毫秒)
private long totalCpuTime=0L;//以毫秒为单位的总CPU时间
private double load=0d;//间隔内的平均负载
ThreadMXBean ThreadMXBean=ManagementFactory.getThreadMXBean();
布尔停止=假;
@凌驾
公开募捐{
试一试{
而(!isStopped()){
长启动=System.currentTimeMillis();
long[]ids=threadMXBean.getAllThreadIds();
长时间=0L;
用于(长id:id){
long l=threadMXBean.getThreadCpuTime(id);
如果(l>=0L)时间+=l;
}
long newCpuTime=时间/100000ml;
已同步(此){
long oldCpuTime=总CPUTIME;
totalCpuTime=newCpuTime;
//负载=CPU时间差/所有CPU的运行时间之和
load=(双精度)(新CPUTIME-旧CPUTIME)/
(双精度)(INTERVAL*Runtime.getRuntime().availableProcessors());
}
长睡眠时间=间隔-(System.currentTimeMillis()-start);
睡眠时间