2014-12-05 2 views
0

자바에서 동기화를 연구 중입니다. 나는 CountDownLatch의 정확한 메커니즘을 이해할 수 없다.CountDownLatch는 Java에서 어떻게 작동합니까?

CountDownLatch 은 선언시 주어진 스레드 수에 따라 (스레드 수 완료를 기다리는) 래치를 카운트 다운합니까? (스레드 풀에서)

7 스레드가 ExecutorService에 의해 산란된다 : 위의 예에서

public class LatchExample implements Runnable { 
    private CountDownLatch latch; 

    private int id; 

    public LatchExample(int id, CountDownLatch latch){ 
     this.id=id; 
     this.latch = latch; 
    } 

    public static void main(String[] args) { 

     CountDownLatch latch = new CountDownLatch(5); 

     ExecutorService executor = Executors.newFixedThreadPool(3); 

     for (int i = 0; i < 7; i++) { 
      executor.submit(new LatchExample(i,latch)); 
     } 

     try { 
      latch.await(); 
      System.out.println("all process completed"); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 


     System.out.println(); 
    } 

    @Override 
    public void run() { 

     System.out.println("Starting: "+id); 
     try { 
      Thread.sleep(1000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     latch.countDown(); 
    } 
} 

: 여기

내가 이해하려고 노력 코드입니다.

CountDownLatch latch = new CountDownLatch(5); 

하지만 얻을 출력이 일정 할 때마다되지 않습니다 : 나의 이해에 의해 정의 된 래치 (0 ~ 5) (6 개) 스레드가 완료 될 때까지 기다립니다해야한다는 것입니다.

Starting: 0 
Starting: 2 
Starting: 1 
Starting: 4 
Starting: 5 
Starting: 3 
all process completed 

Starting: 6 

편집 : :이 CountDownLatch를 이상적으로 카운트 다운이 5 개 작업이를 전달해야 할 때까지

다음
Starting: 1 
Starting: 0 
Starting: 2 
Starting: 3 
Starting: 5 
Starting: 4 
Starting: 6 
all process completed 

다른 시간에 출력은 : 6 스레드가 완료 될 때까지 때로는 7 예를 대기 위해 때때로 기다립니다 걸쇠. 여기에 6 또는 7 중 하나로 표시됩니다. '모든 프로세스가 완료되었습니다' 전에 항상 5 개의 작업 만 표시하려면 코드의 수정 내용은 무엇입니까?

+0

왜 'CountDownLatch'가 5가 아닌 7입니까? [CountDownLatch] (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html)의 java 문서에있는 예제에서'N'을보십시오 – Jack

+0

@Jack 만약 내가 단 5 ~ 6 개의 스레드 만 완료되기를 기다리고 싶습니까? 그래서 이유가 있습니다. – Anurag

+0

그럼 제대로 작동합니다. 한 번에 둘 이상의 스레드가 실행될 수 있기 때문에 경쟁 조건이 있습니다 ... Executors.newFixedThreadPool (3); ' – Jack

답변

0

CountDownLatch는 숫자로 초기화됩니다.이 숫자는 await()에서 대기중인 스레드가 처리되기 전에 countDown()이 호출되어야하는 횟수를 의미합니다.

new CountDownLatch(5) 

카운트 다운() 5 번 호출해야하며, 그런 다음에야 AWAIT에 대기 스레드() procced 수 있습니다. 코드를

new CountDownLatch(7) 
0

으로 변경하십시오. 스레드와 독립적입니다.

누군가 카운트 다운 래치를 기다리면 카운터가 0이 아닌 경우 차단됩니다. 카운터가 0에 도달 할 때까지 또는 시간 제한에 도달 할 때까지 차단을 계속합니다 (시간 제한을 기다리는 버전을 호출 한 경우).

하나의 스레드가 작업을 수행하고 해당 카운터를 줄이거 나 수행 할 작업을 기다리는 다른 스레드를 가질 수 있습니다. 당신은 또한 1의 값을 가진 카운트 다운 래치를 가질 수 있고 다른 스레드가 GUI를 빌드하는 동안 초기화를 할 수 있습니다. 그런 다음 GUI가 보이기 전에 래치에 메인 스레드 블록을 놓습니다. 많은 가능성이 있습니다.

4

래치가 0이 되려면 countDown() 건 전화가 필요하고 await이 반환되어야합니다. 그러나 실행 프로그램에 대한 태스크가 작성되는 방식으로 래치를 해제하는 데 필요한 것보다 많은 태스크가 실행되기 시작합니다.코드 위치를 확인하는 가장 유용한 방법은 다음과 같이 단계별로 실행 단계를 거치고 있습니다.

  • 개의 태스크가 3 개의 스레드 풀 스레드에서 실행되기 시작합니다.
  • Starting: n이 세 번 인쇄 된 것을 볼 수 있습니다. 여기에서 n은 0과 2 사이의 값이지만 임의의 순서로 표시됩니다.
  • 두 번째 패스;
  • 3 개의 작업이 거의 동시에 완료되어 래치의 수를 2로 낮 춥니 다.
  • 작업 3-5 시작;
  • Starting: n이 3 번 인쇄되고, n은 3과 5 사이의 임의의 순서로 표시됩니다.
  • 다른 두 번째 패스;
  • 작업 3-5가 거의 동시에 완료되면 래치가 해제됩니다. 이제 메인 스레드는 계속 진행할 수 있고 태스크 6을 시작할 수 있습니다.
  • all processes completed은 임의의 순서로 Starting: 6과 거의 동시에 인쇄합니다.
  • 이제 코드가 수행 할 것으로 예상되는 내용이 명확하지 않지만 위의 추론 방법이 해당 동작을 기대와 일치하는 상태로 가져 오는 데 도움이되기를 바랍니다.

    1

    countDownLatch 뒤에있는 메커니즘을 이해하는 가장 좋은 방법은 비유를하는 것입니다. 따라서 내 2 센트는 다음과 같이 진행됩니다. 디스코 파티를 생각하면 DJ가됩니다. 좋아하는 노래를 넣으십시오. "모두 처리 완료 "까지 카운트 댄스 플로어에 5 명이 있습니다. 누군가가 들어올 때마다 카운트 다운 (5에서)하고 0에 도달하면 좋아하는 노래를 넣습니다. 댄스 플로어에 모두 모여 있더라도 상관 없습니다. 댄스 플로어에서 5 명을 뽑았다는 점에 신경을 써야합니다.

    예를 들어 countDownLatch = 5를 입력하고 for 루프의 문자 수는 < 7입니다. 괜찮습니다. 그래서 5 명의 댄서가 들어올 때 - 당신은 노래를 "모든 과정이 끝났습니다."라고 말합니다. 그래서 결과는 괜찮습니다.

    당신은 질문 : 선언에 주어진 스레드의 수에 따라 (스레드 수의 완료를위한 대기)

    합니까 CountDownLatch를 '래치 카운트 다운'?

    아니요, 스레드가 완료 될 때까지 기다리지 않고 스레드에 전혀 신경 쓰지 않습니다. 카운트가 중요합니다.

    현실에서는 모든 스레드가 특정 작업을 수행했는지 확인하고 이제 주 (또는 다른 스레드)를 계속 사용할 준비가되었을 때이 메커니즘을 사용합니다.

    0

    CountDownLatch을 사용하면 스레드를 통과시킬 수 있습니다. countDown 모든 래치가 래치에서 사용 가능합니다.

    이 경우 5 개의 허가가 있지만 개의 스레드가 있으므로 5 번째 스레드가 래치를 잠금 해제하고 프로그램이 계속됩니다. 하지만 여전히 2 개의 스레드가 남아 있습니다.

    래치가 잠금 해제되었으므로 countDown의 허가가 없기 때문에 프로그램은 마지막 2 개의 스레드없이 계속됩니다. 이 문제를 해결하려면 5 대신 7 개의 허가가 필요합니다.

    1

    내 대답은 너무 늦기는하지만, 내게 스레드에 익숙하지 않은 사람에게 도움이되기를 바랍니다. 내 분석에 따라 카운트 다운 래치가 의도 한대로 작동합니다. 이 변경을 수행하고 결과를 확인하십시오.

    @Override 
    public void run() { 
    
        //System.out.println("Starting: "+id); 
        try { 
         Thread.sleep(1000); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
    
        latch.countDown(); 
        System.out.println("Finished the thread: "+id); 
    } 
    
    관련 문제