2013-03-16 2 views
0

나는 프로그램으로 촬영 한 총 시간과 프로그램이 평균 시간을 측정해야하는 프로젝트를 진행 중입니다. 그리고 그 프로그램은 멀티 스레드 프로그램입니다.걸린 총 시간과 모든 스레드에 의해 걸린 평균 시간

해당 프로그램에서 각 스레드는 특정 범위에서 작동합니다. 입력 매개 변수는 Number of ThreadsNumber of Task입니다.

number of threads is 2number of tasks is 10 인 경우 각 스레드는 10 tasks을 수행합니다. 즉 2 스레드가 20 tasks 일을 의미합니다.

그래서 수단 -

첫 번째 스레드 11 and 20 사이 ID를 사용한다 1 and 10 및 제 스레드 사이 ID를 사용한다.

위의 시나리오가 작동했습니다. 이제 모든 스레드가 취하는 총 시간과 평균 시간을 측정하고 싶습니다. 그래서 나는 아래 프로그램을 내 프로그램에 넣었다.

문제 설명 : -

사람이 나에게 나는 모든 스레드에 의해 Total time and Average time taken을 측정하려고하는 방법을 말할 수 내 아래 프로그램에서 올바른 아닌지?

//create thread pool with given size 
ExecutorService service = Executors.newFixedThreadPool(noOfThreads); 

long startTime = 0L; 
try { 

    readPropertyFiles(); 

    startTime = System.nanoTime(); 

    // queue some tasks 
    for (int i = 0, nextId = startRange; i < noOfThreads; i++, nextId += noOfTasks) { 

     service.submit(new XMPTask(nextId, noOfTasks, tableList)); 
    } 

    service.shutdown(); 
    service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 

} finally { 
    long estimatedTime = System.nanoTime() - startTime; 
    logTimingInfo(estimatedTime, noOfTasks, noOfThreads); 
} 



private static void logTimingInfo(long elapsedTime, int noOfTasks, int noOfThreads) { 

    long timeInMilliseconds = elapsedTime/1000000L; 
    float avg = (float) (timeInMilliseconds)/noOfTasks * noOfThreads; 

    LOG.info(CNAME + "::" + "Total Time taken " + timeInMilliseconds + " ms. And Total Average Time taken " + avg + " ms"); 
} 

답변

0

service.submitnoOfThreads 번 실행지고 있습니다. XMPTask 개체가 동일한 횟수만큼 생성됩니다.

0

측정 시간이 시간이 아니며 시간이지만 시간이 경과 한 시간은입니다.

테스트 된 프로그램 (JVM)이 컴퓨터에있는 유일한 프로그램 인 경우 비교적 정확할 수 있지만 실제 환경에서는 많은 프로세스가 동시에 실행됩니다.

나는 Windows에서이 기본 코드 (월요일에 사무실)와 Linux (/ proc)를 작성하여이 작업을 이미 수행했습니다.

+0

그냥 위의 프로그램, 나는 우리 LNP 테스트를 위해 나에게 전용으로 사용되는 컴퓨터에서 실행됩니다. – AKIWEB

0

여러분은 작업 클래스 자체 (XMPTask) 내에서 시간을 측정해야한다고 생각합니다. 해당 작업 내에서 실행중인 스레드의 ID를 추출하여 기록 할 수 있어야합니다. 이 방법을 사용하려면 로그를 읽고 로그에 대한 계산을 수행해야합니다.

또 다른 방법은 시간 경과에 따라 총계 및 평균을 계속 실행하는 것입니다. 이를 위해 각 스레드가 수행하는 작업을 추적 할 수있는 정적 (jvm 당) 변수가있는 각 작업에 전달되는 간단한 클래스를 작성할 수 있습니다. 그런 다음 계산을 수행 한 스레드 풀 외부에 단일 스레드를 가질 수 있습니다. 따라서 매 초마다 각 스레드의 평균 CPU 시간을보고하려면이 계산 스레드가 잠시 동안 잠자기 상태가되어 평균 시간을 모두 계산하여 기록한 다음 잠시 기다리십시오 ...

EDIT : After 요구 사항을 다시 읽으면 백그라운드 스레드는 필요하지 않지만 스레드 당 평균 시간 또는 작업 당 평균 시간을 추적하는지 확실하지 않습니다. 나는 스레드 당 총 시간과 평균 시간을 가정하고 아래 코드에서 아이디어를 구체화했습니다.그것은 테스트하거나 디버깅하지만 당신이 시작하는 방법의 좋은 아이디어를 제공해야되지 않은 :이 모든 것을 작성 후

public class Runner 
{ 
    public void startRunning() 
    { 
     // Create your thread pool 
     ExecutorService service = Executors.newFixedThreadPool(noOfThreads); 

     readPropertyFiles(); 

     MeasureTime measure = new MeasureTime(); 

     // queue some tasks 
     for (int i = 0, nextId = startRange; i < noOfThreads; i++, nextId += noOfTasks) 
     { 

      service.submit(new XMPTask(nextId, noOfTasks, tableList, measure)); 
     } 

     service.shutdown(); 
     service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
     measure.printTotalsAndAverages(); 
    } 
} 

public class MeasureTime 
{ 
    HashMap<Long, Long> threadIdToTotalCPUTimeNanos = new HashMap<Long, Long>(); 
    HashMap<Long, Long> threadIdToStartTimeMillis = new HashMap<Long, Long>(); 
    HashMap<Long, Long> threadIdToStartTimeNanos = new HashMap<Long, Long>(); 

    private void addThread(Long threadId) 
    { 
     threadIdToTotalCPUTimeNanos.put(threadId, 0L); 
     threadIdToStartTimeMillis.put(threadId, 0L); 
    } 

    public void startTimeCount(Long threadId) 
    { 
     synchronized (threadIdToStartTimeNanos) 
     { 
      if (!threadIdToStartTimeNanos.containsKey(threadId)) 
      { 
       addThread(threadId); 
      } 

      long nanos = System.nanoTime(); 
      threadIdToStartTimeNanos.put(threadId, nanos); 
     } 
    } 

    public void endTimeCount(long threadId) 
    { 
     synchronized (threadIdToStartTimeNanos) 
     { 
      long endNanos = System.nanoTime(); 
      long startNanos = threadIdToStartTimeNanos.get(threadId); 

      long nanos = threadIdToTotalCPUTimeNanos.get(threadId); 
      nanos = nanos + (endNanos - startNanos); 
      threadIdToTotalCPUTimeNanos.put(threadId, nanos); 
     } 
    } 

    public void printTotalsAndAverages() 
    { 
     long totalForAllThreadsNanos = 0L; 
     int numThreads = 0; 
     long totalWallTimeMillis = 0; 
     synchronized (threadIdToStartTimeNanos) 
     { 
      numThreads = threadIdToStartTimeMillis.size(); 
      for (Long threadId: threadIdToStartTimeNanos.keySet()) 
      { 
       totalWallTimeMillis += System.currentTimeMillis() - threadIdToStartTimeMillis.get(threadId); 
       long totalCPUTimeNanos = threadIdToTotalCPUTimeNanos.get(threadId); 

       totalForAllThreadsNanos += totalCPUTimeNanos; 
      } 
     } 

     long totalCPUMillis = (totalForAllThreadsNanos)/1000000; 
     System.out.println("Total milli-seconds for all threads: " + totalCPUMillis); 
     double averageMillis = totalCPUMillis/numThreads; 
     System.out.println("Average milli-seconds for all threads: " + averageMillis); 

     double averageCPUUtilisation = totalCPUMillis/totalWallTimeMillis; 
     System.out.println("Average CPU utilisation for all threads: " + averageCPUUtilisation); 
    } 
} 

public class XMPTask implements Callable<String> 
{ 
    private final MeasureTime measure; 

    public XMPTask(// your parameters first 
      MeasureTime measure) 
    { 
     // Save your things first 

     this.measure = measure; 
    } 

    @Override 
    public String call() throws Exception 
    { 
     measure.startTimeCount(Thread.currentThread().getId()); 

     try 
     { 
      // do whatever work here that burns some CPU. 
     } 
     finally 
     { 
      measure.endTimeCount(Thread.currentThread().getId()); 
     } 

     return "Your return thing"; 
    } 
} 

을의 XMPTask가에 대해 너무 많이 알고 보인다는 점에서 조금 이상한 것 한 가지가있다 작업 목록, 언제든지 모든 작업에 대해 XMPTask를 작성하고 작업을 수행 할 수있는 충분한 정보를 제공하고 작성시 서비스에 제출해야한다고 생각합니다.

+0

제안에 대해 hack_on에게 감사드립니다. 두 번째 방법은 좋은 생각입니다. 두 번째 접근 방식에 대한 간단한 예제를 제공해 줄 수 있습니까? 도와 주셔서 감사합니다. – AKIWEB

관련 문제