2010-01-28 5 views
2

저는 java.util.concurrent 패키지를 사용하고 있습니다. 숫자가 멀티 및 단일 스레드 전략을 사용하는 소수라면 다음 프로그램 테스트를 작성했습니다. 방법 에 대한java.util.concurrent : 소수 계산

import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 


public class IsPrime 
     implements Runnable 
    { 
    private static final long UPPER_BOUND=100000; 
    long value;//the number observed 
    private IsPrime(long value) 
     { 
     this.value=value; 
     } 
    /** returns wether value is a prime number (simple and stupid method) */ 
    private boolean isAPrimeNumber() 
     { 
     if(value==1 || value==2) return true; 
     if(value%2L==0) return false; 
     for(long i=3;i< value;++i) 
      { 
      if(this.value%i==0) return false; 
      } 
     return true; 
     } 

    @Override 
    /** calls isAPrimeNumber */ 
    public void run() 
     { 
     boolean result=isAPrimeNumber(); 
     //if(result) System.out.println("["+this.value+"]"); 
     } 

    /** loop from 3 to UPPER_BOUND, multithreaded */ 
    private static long loopMT() 
     { 
     long now=System.currentTimeMillis(); 
     ExecutorService service=Executors.newFixedThreadPool(10); 

     for(long i=3;i< UPPER_BOUND;i+=2) 
      { 
      service.submit(new IsPrime(i)); 
      } 
     service.shutdown(); 
     return System.currentTimeMillis()-now; 
     } 

    /** loop from 3 to UPPER_BOUND, NOT multithreaded */ 
    private static long loop() 
     { 
     long now=System.currentTimeMillis(); 
     for(long i=3;i< UPPER_BOUND;i+=2) 
      { 
      new IsPrime(i).run(); 
      } 
     return System.currentTimeMillis()-now; 
     } 

    public static void main(String[] args) 
     { 
     long n1=IsPrime.loop(); 
     long n2=IsPrime.loopMT(); 
     System.out.println(""+n1+" >>> "+n2); 
     } 
    } 

은 패키지 java.util.concurrent의의 클래스를 사용하는 올바른 방법입니다,을 loopMT? 이 프로그램을 작성하는 또 다른 (더 안전하고 더 우아한) 방법이 있습니까? System.out을 멀티 스레드 환경에서 사용할 수 있습니까? 귀하의 제안은 현재 완료하기 위해 제출 된 작업을 기다리고되지 loopMT을 기록되면

피에르

+0

왜 '호출 가능 '대신'Runnable'을 구현하고 있습니까? – finnw

+0

정말 반환 값이 필요하지 않습니다. 내 진정한 프로그램 (이 프로그램이 아님)에서는 시간이 많이 걸리는 프로세스의 결과 만 인쇄하면됩니다. 이것이 내가 'void run (void)'에서 System.out을 주석 처리 한 이유입니다. – Pierre

+0

질문 제목은 오해의 소지가 있습니다. 다중 코어 CPU에서 소수를 계산하는 데 최적화 된 방법을 찾은 것 같습니다. :) 그런 다음 나에게 분명히해라. System.out 인쇄 된 소수가 순서대로 인쇄 되길 원하니? – SyntaxT3rr0r

답변

1

에 대한

많은 감사합니다. 모든 소수성 테스트가 완료 될 때까지 당신이 현재하고있는 것처럼 System.out에 결과를 기록, 기다릴

  • 전화 awaitTermination() :

    당신은 몇 가지 옵션이 있습니다.
  • 변경 Callable<Boolean>-Runnable에서 인터페이스 아니면 Callable<Map.Entry<Long, Boolean>> 및 사용 service.invokeAll() 동기화 Map에서
  • 스토어 결과를 (당신은. 모든 결과를 한 번에 반환 얻을 것이다) 모든 소수성 테스트는
  • 을 완료하면 그것을 읽고
  • run 메서드가 결과를 BlockingQueue 또는 SynchronousQueue으로 보내고 loopMT 메서드가 큐에서 결과를 반입하고 인쇄하도록합니다. 이것이 제가 선호하는 선택입니다.
  • CompletionService을 통해 간접적으로 대기열을 사용하십시오.
+0

'SynchronousQueue'는 실제로 채널과 비슷합니다. 나는 그것이 여기 적절하다고 생각하지 않습니다.그리고 왜 동기화 된 맵을 사용하지만'ConcurrentMap'을 사용하지 않는가? 대부분의 경우 처리량이 훨씬 좋습니다. – Rorick

+0

예'SynchronousQueue'는 채널이고, 다른 스레드가 그것을 읽지 못하게하는 경우 원하는 것입니다. 이것이 제가 제안하고있는 것입니다. ConcurrentMap은 괜찮습니다. (여분의 메소드는 필요 없습니다.) – finnw

1

이 계산은 CPU 바인딩 가능성이 높기 때문에 CPU 코어보다 많은 스레드를 실행하는 이점이 없습니다. 이후 여분의 스레드는 오버 헤드에만 추가됩니다.

2

System.outPrintStream의 인스턴스이므로 스레드로부터 안전합니다. 따라서 훈련 예는 괜찮습니다. 그러나 일반적으로 다른 스레드의 출력은 나에게 좋은 생각처럼 보이지 않습니다. 비동기 적으로 출력 요청을 허용하는 전용 출력 스레드를 갖는 것이 좋습니다.

필자는 아마도을 finnw로 구현 했겠지만 그렇지 않으면 CPU 소비를 제외하고는 IsPrime 클래스에서 아무런 이유가 없다고 생각합니다.