CountdownLatch는 유용한 도구 클래스입니다. 그것을 사용하여 특정 조건이 익은 후 하나 이상의 스레드를 가로 채어 실행할 수 있습니다. 내부 컨텐츠는 카운터를 제공하며 잠금을 구성 할 때 카운터의 초기 값을 지정해야하며 카운터의 초기 값은 0보다 크관이어야합니다. 또한 카운터 값을 작동시키기위한 카운트 다운 방법을 제공합니다. 카운트 다운 방법이 호출 될 때마다 카운터가 1으로 줄어 듭니다. 카운터 값이 0으로 감소되면 조건이 익으며 차선 방법을 호출하여 차단 된 모든 실이 깨어납니다. 이것은 CountdownLatch의 내부 메커니즘입니다. 그것은 매우 간단 해 보이며, 스레드를 차단하고 특정 조건에 도달 한 후 실행할 수있는 것 이상입니다. 그러나 CountdownLatch에는 광범위한 응용 프로그램 시나리오가 있습니다. 큰 마음이 있고 사용하는 한 다양한 트릭을 연주 할 수 있습니다. 가장 일반적인 응용 프로그램 시나리오는 여러 스레드가 동시에 작업을 실행 한 다음 모든 작업이 실행 된 후 결과를 계산하고 요약하는 것입니다. 다음 그림은 스레드 차단의 전체 프로세스를 동적으로 보여줍니다.
위의 그림은 차선 방법을 호출하여 5 개의 스레드가 차단되었으며, 계속 실행되기 전에 카운터 값이 0으로 감소 할 때까지 기다려야합니다. 카운터의 초기 값은 잠금을 구성 할 때 지정된 후 카운트 다운 방법에 대한 각 호출마다 1만큼 감소됩니다. 다음 코드는 CountdownLatch Construction 방법을 게시합니다.
// 생성자 public countdownlatch (int count) {if (count <0) 새로운 불법 불법 행위 ( "count <0"); this.sync = new sync (count); }CountdownLatch에는 하나의 매개 변수 생성자 만 있으며 카운터의 초기 값으로 0보다 큰 값을 전달해야합니다. 그렇지 않으면 오류 가보고됩니다. 생성자에서 새로운 동기화 객체만으로도 멤버 변수 동기화에 할당하는 것을 볼 수 있습니다. 다른 동기화 도구 클래스와 마찬가지로 CountdownLatch의 구현은 AQS 공유 모드의 응용 프로그램 인 AQS에 의존합니다. CountdownLatch는 내부 클래스 동기화를 구현하고이를 사용하여 AQ가 제공하는 대부분의 방법을 사용할 수 있도록 AQ를 상속합니다. 동기화 내부 클래스 코드를 살펴 보겠습니다.
// synchronizer private static final class sync 확장 actractqueuedsynchronizer {// 생성자 sync (int count) {setstate (count); } // 현재 동기화 상태를 가져옵니다. int getCount () {return getState (); } // 잠금을 얻으려고 시도하십시오. // return negative numb 1 : -1; } // 잠금을 해제하려고 노력하십시오. 보호 된 부울 tryreleaseShared (int 릴리스) {for (;;) {// 동기화 상태 int c = getState (); // 동기화 상태가 0이면 if (c == 0) {return false; } // 그렇지 않으면 동기화 상태를 1 int nextc = c-1로 줄입니다. // CAS 메소드를 사용하여 동기화 상태를 업데이트하면 if (CompareAndsetState (C, NextC)) {return nextc == 0; }}}}Sync의 생성자가 동기화 상태의 값을 전달 된 매개 변수 값으로 설정한다는 것을 알 수 있습니다. 그 후, 카운트 다운 방법이 호출 될 때마다 동기 상태의 값은 1만큼 줄어 듭니다. 이는 카운터의 구현 원리입니다. CountdownLatch 도구 클래스를 사용할 때 가장 일반적으로 사용되는 두 가지 방법은 Await 방법과 카운트 다운 방법입니다. 대기 방법을 호출하면 카운터가 0이 될 때까지 현재 스레드가 차단되며 카운트 다운 메소드를 호출하면 카운터 값이 0으로 줄어들 때까지 카운터 값이 1 씩 줄어 듭니다. 차단 방법이 어떻게 호출되는지 살펴 보겠습니다.
// 래치가 0으로 감소하거나 스레드가 중단 될 때까지 대기 스레드가 대기 할 수있게되며, 공개 void await await await await await await await awaitexception {// sync.acquiresharedinterpruptility (1);} // 잠금을 중단 획득 (Int -Argruber -harrubedinterpruptility에서 공유 모드)에서 획득합니다. if (ride.interrupted ()) {throw new InterruptedException (); } // 1. (tryacquireshared (arg) <0) {// 2. 취득이 실패하면 doacquiresharedinterpruptily (arg) 메소드를 입력하십시오. }}스레드가 AWAIT 메소드를 호출하면 실제로 AQS의 AcquiResharedInterpruptibly 메소드를 호출합니다. 이 방법은 스레드 인터럽트에 대한 응답으로 잠금을 획득합니다. 이 방법의 코드도 위에 게시됩니다. arcumeResharedinterpruptility 방법에서 먼저, 자물쇠를 획득하기 위해 tryacquireshared 방법을 호출 할 것임을 알 수 있습니다. 우리는 tryacquireshared 방법의 논리가 동기화되어 다시 작성된 것을 봅니다. 이 방법의 구현 로직은 매우 간단합니다. 이것은 현재 동기화 상태가 0인지 판단하는 것입니다. 0 인 경우, 반환 1은 잠금을 획득 할 수 있음을 의미합니다. 그렇지 않으면 -1은 잠금을 얻을 수 없음을 의미합니다. TreeAcquireshared 메소드가 1을 반환하면 스레드가 기다리지 않고 계속 실행할 수 있습니다. -1이 반환되면 DoacquiresharedInterpruptility 방법이 동기 대기열에서 호출되어 대기합니다. 이것이 대기 방법을 호출하면 현재 스레드를 차단한다는 원칙입니다. 카운트 다운 메소드가 어떻게 차단 스레드를 깨우는 지 살펴 보겠습니다.
// 래치를 줄이는 방법 public void countdown () {Sync.ReleasShared (1);} // 릴리스 작업 (공유 모드) 공개 최종 부울 릴리스 셰어 (int arg) {// 1. if (tryReleasShared (arg)) {// 2. 릴리스가 성공하면 다른 스레드 DoreLeasShared ()를 깨우십시오. 진실을 반환하십시오. } return false;}카운트 다운 방법에서 해지 방법이 호출된다는 것을 알 수 있습니다. 이 방법은 또한 AQS의 메소드입니다. 우리는 또한 코드를 게시했습니다. 방출 방법의 첫 번째는 TryReleasShared 방법을 호출하여 잠금을 해제하는 것입니다. TryReleasShared 방법은 AQS의 추상 방법입니다. 특정 구현 로직은 서브 클래스 동기화 클래스에 있습니다. 위에 게시 된 동기화 클래스 코드 에서이 메소드를 찾을 수 있습니다. TryReleAsShared 메소드가 릴리스되어 릴리스를 반환하고 False를 반환하여 실패를 릴리스합니다. 1을 줄인 후 동기화 상태가 정확히 0 인 경우에만 true를 반환합니다. 다른 경우에는 거짓이 반환됩니다. 그런 다음 TryReleasShared가 true를 반환하면 DoreLeasShared 방법이 즉시 호출되어 동기화 큐의 모든 스레드를 깨우게됩니다. 이는 카운터를 마지막으로 카운터를 0으로 줄이기 위해 마지막으로 호출되는 이유를 설명합니다. 이것들은 CountdownLatch의 기본 원칙입니다. 사용의 예를 살펴 보겠습니다.
애플리케이션 시나리오 : 행복한 집주인을 플레이 할 때는 카드를 다루기 전에 세 명의 선수가 모두 도착할 때까지 기다려야합니다.
공개 클래스 플레이어는 스레드를 확장합니다 {private static int count = 1; 개인 최종 int id = count ++; 개인 CountdownLatch Latch; 공개 플레이어 (CountdownLatch Latch) {this.latch = Latch; } @override public void run () {System.out.println ( "【플레이어" + id + "] 항목"); latch.countdown (); } public static void main (string [] args)은 중단 exception {countdownlatch latch = new CountdownLatch (3); System.out.println ( "게임이 시작되어 플레이어가 들어 오기를 기다립니다 ..."); 새 플레이어 (Latch) .start (); 새 플레이어 (Latch) .start (); 새 플레이어 (Latch) .start (); latch.await (); System.out.println ( "플레이어가 도착했습니다. 거래 시작 ..."); }}운영 결과는 모든 플레이어가 현장에 들어간 후 거래 작업이 수행되어야 함을 보여줍니다. 23 줄 latch.await ()에 주석을 달고 결과를 확인하기 위해 비교합니다.
라인 Latch.await ()에 댓글을 달린 후 모든 플레이어가 필드에 들어간 후에 만 카드를 처리하기 시작한다는 것을 보장하지는 않습니다.
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.