2012-12-12 1 views
0

병렬 수집을 종료하는 가장 좋은 방법은 무엇입니까 (스레드 중 하나가 던진 예외 또는 사용자가 시작한 인터럽트 인 경우).GPars - 병렬 수집을 일찍 종료하는 올바른 방법

어느 경우이든 쉽게 플래그를 설정하고 루프 맨 위에서 확인하면됩니다. 그러나 컬렉션에 10,000 개의 항목이있는 경우 ForkJoinPool에 피드를 중지하도록 지시하는 것이 좋습니다. 이미 시작한 5 ~ 20 개의 항목을 끝내지 만 더 이상 시작하지 마십시오.

다음은 내가 무슨 뜻인지 알아보기 위해 사용할 수있는 샘플입니다. 스레드 중 하나에 의해 예외가 발생하는 것을 시뮬레이션하면 스레드 카운트의 첫 번째 인쇄 ('A :'메시지)가 종종 매우 작기 때문에 (5 개 정도) 콜렉션이 처리를 중지하는 것처럼 보입니다. 그러나 ('B'에서)을 GParsPool.withPool의 외부 카운트를 인쇄하여, 나는 그들이 정말 (항상 모든 100)을 실행 유지 것을 볼 수 있습니다

void doIt() { 
    AtomicInteger threadCounter = new AtomicInteger(0) 
    AtomicInteger threadCounterEnd = new AtomicInteger(0) 

    try { 
     GParsPool.withPool { pool -> 

      try { 
       (1..100).eachParallel { 
        try { 
         if (threadCounter.incrementAndGet() == 1) { 
          throw new RuntimeException('planet blew up!') 
         } 

         // Do some long work 
         Integer counter=0 
         (1..1000000).each() {counter++} 

         // Flag if we went all the way through 
         threadCounterEnd.incrementAndGet() 
        } catch (Exception exc) { 
         //pool.shutdownNow() 
         throw new RuntimeException(exc) 
        } 
       } 
      } catch (Exception exc) { 
       println 'caught exception' 
       //pool.shutdownNow() 
       println "A: threads launched was ${threadCounter}, ended was ${threadCounterEnd}" 
       throw new RuntimeException(exc) 
      } 
     } 
    } catch (Exception exc) { 
     exc.printStackTrace() 
    } 

    println "B: threads launched was ${threadCounter}, ended was ${threadCounterEnd}" 
} 

내가 pool.shutdown를 사용하는 경우() 안에 eachParallel, 아무런 영향을 미치지 않습니다. pool.shutdownNow()를 사용하면 원하는대로 처리가 끝나지만 CancellationException이 발생하여 실제 예외가 보이지 않게됩니다. 나중의 액세스를 위해 '실제'예외를 변수에 저장할 수는 있지만, 병렬 수집을 완전히 중지시키는 더 좋은 방법이 없는지 궁금합니다.

답변

2

ATM과 같은 메커니즘이 없습니다. 풀은 사용자의 타스크와 다른 잠재적 계산의 타스크를 구별 할 수 없으므로 스레드가 타스크 대기열을 읽지 못하도록하는 메커니즘이 없습니다. 스레드 풀의 유일한 사용자라는 것을 알고 있다면 shutdownNow()를 사용할 수 있습니다 (위에서 언급 한 결과와 함께).

내가 알고있는 다른 옵션은 작업의 예외를 올바르게 catch하고 공유 된 원자 플래그를 설정하여 다른 작업이 즉시 종료하도록 지정하는 것입니다.

+0

감사합니다. 하나의 작업에서 예외가 현재 진행중인 병렬 실행을 단락 시키려고합니다. 즉, 현재 'eachParallel'또는 기타 (GPars의 위험한 기본값이 될 수도있는 전체 풀이 아닌 것)를 종료하십시오. 그냥 확인하려면 - shutdown 이제 풀을 종료하는 안전한 방법입니다 - 이전 Thread.stop처럼 위험하지 않습니다. 맞습니까? 언제나처럼 Vaclav, 당신은 훌륭한 질문에 대답하여 GPars를 지원했습니다 (그리고 잘하면 질문뿐만 아니라 다른 사람들을 도울). – user1373467

+0

이 질문과 관련 질문에 대한 해결책의 코드 샘플을 http://stackoverflow.com/questions/13771337/how-know-with-gpars-that-all-threads-have-finished-when-an- 예외가 발생했습니다./13824965 # 13824965 – user1373467