한 가지 방법은 4 maximum pool size 시작하고 메모리와 CPU 사용량에 따라 동적으로 최대 풀 크기를 조정 1의 core size, 함께 ThreadPoolExecutor을 사용하는 것입니다.
더 큰 문제는 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;
}
}