2014-09-14 1 views
3

내 응용 프로그램은 Executor를 사용하여 많은 수의 작업에 대한 스레드 풀을 제공합니다. 분석 및 벤치마킹을 통해 코어 당 스레드가 여러 개인 경우 응용 프로그램이 가장 빠르게 실행됩니다. 좋은 경험적 방법은 코어 당 4 개의 스레드로 시작하여 CPU가 90 % 이상이거나 RAM이 90 % 이상이 될 때까지 다양합니다.CPU 및 RAM 사용량에 따라 스레드 풀을 조정하는 Java Executor

즉시 사용할 수있는 Executor가 있습니까? 코어 당 N 개의 스레드를 자동으로 사용하거나 아니면 CPU 및 RAM 사용량에 따라 스레드 풀 크기를 조절하는 것이 가장 이상적입니까?

실패 - 프로그래밍 방식으로 코어 수를 어떻게 결정합니까?

답변

1
Runtime.availableProcessors() 

자바 독 :

자바 가상 머신이 이용 가능한 프로세서의 수를 돌려줍니다. 이 값은 가상 컴퓨터의 특정 호출 중에 변경 될 수 있습니다. 따라서 사용 가능한 프로세서 수에 민감한 응용 프로그램은 때때로이 속성을 폴링하고 리소스 사용을 적절하게 조정해야합니다.

2

한 가지 방법은 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; 
    } 
} 
관련 문제