Java 멀티스레딩에서 Count Down Latch는 어떻게 사용됩니까?
자바가 어떤 좀 요?CountDownLatch
제사 ??
나는 이 프로그램이 어떻게 작동하는지 잘 모르겠다.3개의 스레드가 동시에 시작되고 3000밀리초 후에 각 스레드가 CountDownLatch를 호출하는 것으로 알고 있습니다.카운트다운은 1개씩 감소합니다.래치가 제로가 되면, 프로그램에 「Completed」라고 표시됩니다.아마 제가 잘못 이해한 것 같아요.
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class Processor implements Runnable {
private CountDownLatch latch;
public Processor(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
System.out.println("Started.");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}
// -----------------------------------------------------
public class App {
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(3); // coundown from 3 to 0
ExecutorService executor = Executors.newFixedThreadPool(3); // 3 Threads in pool
for(int i=0; i < 3; i++) {
executor.submit(new Processor(latch)); // ref to latch. each time call new Processes latch will count down by 1
}
try {
latch.await(); // wait until latch counted down to 0
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Completed.");
}
}
잘 요. CountDownLatch
래치 원리로 작동하며, 메인 스레드는 게이트가 열릴 때까지 기다립니다.1개의 스레드는 n개의 스레드를 대기하며,CountDownLatch
.
를 하는, 통상은 , 의 스레드CountDownLatch.await()
카운트가 0이 될 때까지 기다리거나 다른 스레드에 의해 중단됩니다. 모든 .CountDownLatch.countDown()
성되완
카운트가 0이 되면 대기 스레드가 계속됩니다.★★★★★★★★★★★★★★★★의 단점 중 하나CountDownLatch
0을 사용할 수 .CountDownLatch
★★★★★★★★★★★★★★★★★★.
편집:
CountDownLatch
한 스레드(메인 스레드 등)가 처리를 계속하기 위해 하나 이상의 스레드가 완료될 때까지 기다려야 하는 경우.
「 」를하는 예.CountDownLatch
측 Java 서 여러 in Java를 할 수 .여기서 여러 서비스는 여러 스레드에 의해 제공되며 모든 서비스가 정상적으로 시작될 때까지 응용 프로그램은 처리를 시작할 수 없습니다.
P.S. OP의 질문에는 아주 간단한 예가 있기 때문에 포함하지 않았습니다.
CountDownLatch
는 1개의 Java를 하는 입니다.Thread
Thread
시모노
CountDownLatch
래치 원리로 작동합니다. 나사산은 게이트가 열릴 때까지 기다립니다.의 실이 n
시 지정된 스레드 수CountDownLatch
.
★★final CountDownLatch latch = new CountDownLatch(3);
여기서는 카운터를 3으로 설정합니다.
중 하나로, 「」(「」)를 호출합니다.CountDownLatch.await()
이 될 카운트가될 때까지 기다립니다.Thread
을 해야 을 하려면 , 「카운트다운은 입니다.CountDownLatch.countDown()
이 되면 0이 됩니다.Thread
기다리다
서는 숫자가 .CountDownLatch.countDown()
★★★★★★ 。
Thread
는 ""를 호출합니다.await()
메서드는 초기 카운트가 0이 될 때까지 기다립니다.
, 가 「0을할 필요가 있습니다.countDown()
가 , 「0」을 .await()
메서드가 재개됩니다(실행을 시작합니다).
「 」의 CountDownLatch
재사용이 불가능하다는 것입니다. 카운트가 0이 되면 더 이상 사용할 수 없습니다.
NikolaB는 매우 잘 설명했습니다. 하지만 예를 들어 이해하는데 도움이 될 것입니다. 그래서 여기 하나의 간단한 예가 있습니다.
import java.util.concurrent.*;
public class CountDownLatchExample {
public static class ProcessThread implements Runnable {
CountDownLatch latch;
long workDuration;
String name;
public ProcessThread(String name, CountDownLatch latch, long duration){
this.name= name;
this.latch = latch;
this.workDuration = duration;
}
public void run() {
try {
System.out.println(name +" Processing Something for "+ workDuration/1000 + " Seconds");
Thread.sleep(workDuration);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(name+ "completed its works");
//when task finished.. count down the latch count...
// basically this is same as calling lock object notify(), and object here is latch
latch.countDown();
}
}
public static void main(String[] args) {
// Parent thread creating a latch object
CountDownLatch latch = new CountDownLatch(3);
new Thread(new ProcessThread("Worker1",latch, 2000)).start(); // time in millis.. 2 secs
new Thread(new ProcessThread("Worker2",latch, 6000)).start();//6 secs
new Thread(new ProcessThread("Worker3",latch, 4000)).start();//4 secs
System.out.println("waiting for Children processes to complete....");
try {
//current thread will get notified if all chidren's are done
// and thread will resume from wait() mode.
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All Process Completed....");
System.out.println("Parent Thread Resuming work....");
}
}
둘 이상의 스레드가 작업을 완료할 때까지 대기할 때 사용됩니다.스레드 결합과 비슷합니다.
Count Down Latch를 사용할 수 있는 곳
3개의 스레드 "A", "B" 및 "C"가 있으며 "A" 스레드와 "B" 스레드가 작업을 완료하거나 부분적으로 완료했을 때만 스레드 "C"를 시작하려는 시나리오를 생각해 보십시오.
실제 IT 시나리오에 적용할 수 있습니다.
매니저가 개발팀(A와 B)으로 모듈을 분할하여 QA팀에 할당하여 양쪽 팀이 작업을 완료했을 때만 테스트하는 시나리오를 생각해 보십시오.
public class Manager {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(2);
MyDevTeam teamDevA = new MyDevTeam(countDownLatch, "devA");
MyDevTeam teamDevB = new MyDevTeam(countDownLatch, "devB");
teamDevA.start();
teamDevB.start();
countDownLatch.await();
MyQATeam qa = new MyQATeam();
qa.start();
}
}
class MyDevTeam extends Thread {
CountDownLatch countDownLatch;
public MyDevTeam (CountDownLatch countDownLatch, String name) {
super(name);
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println("Task assigned to development team " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Task finished by development team " + Thread.currentThread().getName());
this.countDownLatch.countDown();
}
}
class MyQATeam extends Thread {
@Override
public void run() {
System.out.println("Task assigned to QA team");
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("Task finished by QA team");
}
}
상기 코드의 출력은 다음과 같습니다.
개발팀 devB 작업 할당
개발팀 devA에 할당된 태스크
개발팀 devB에 의해 작업이 완료되었습니다.
개발팀 devA에 의해 작업이 완료되었습니다.
QA팀 태스크 할당
QA팀에 의해 완료되는 작업
여기서 wait() 메서드는 카운트다운래치 플래그가0이 될 때까지 대기하고 countDown() 메서드는 카운트다운래치 플래그를 1씩 줄입니다.
JOIN 제한: 위의 예는 JOIN에서도 실현할 수 있지만 JOIN은 다음 두 가지 시나리오에서 사용할 수 없습니다.
- 스레드 클래스가 아닌 Executor Service를 사용하여 스레드를 만드는 경우.
- 매니저가 80% 태스크를 완료하자마자 코드를 QA팀에게 인계하려는 경우 위의 예를 수정하십시오.즉, Count Down Latch를 사용하면 구현 내용을 수정할 수 있으며, 다른 스레드가 부분 실행되기를 기다리는 데 사용할 수 있습니다.
CoundDownLatch를 사용하면 다른 모든 스레드의 실행이 완료될 때까지 스레드를 대기시킬 수 있습니다.
유사 코드는 다음과 같습니다.
// Main thread starts
// Create CountDownLatch for N threads
// Create and start N threads
// Main thread waits on latch
// N threads completes there tasks are returns
// Main thread resume execution
JavaDoc(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html), CountDownLatch는 Java 5에서 도입된 동기 보조 도구입니다.여기서 동기화는 중요한 섹션에 대한 액세스를 제한하는 것을 의미하지 않습니다.오히려 다른 스레드의 동작의 순서를 지정합니다.CountDownLatch를 통해 얻을 수 있는 동기화 유형은 Join과 유사합니다.다른 작업자 스레드 "T1", "T2", "T3"이 작업을 완료할 때까지 대기해야 하는 스레드 "M"이 있다고 가정합니다. Java 1.5 이전 버전에서는 M이 다음 코드를 실행합니다.
T1.join();
T2.join();
T3.join();
위의 코드는 스레드 M이 T1, T2, T3의 작업을 완료한 후에 작업을 재개하는 것을 보증합니다.T1, T2, T3를 선택합니다.Count Down Latch는 Count Down Latch를 사용합니다.'T1, T2, T3' 'M' 'Count Down Latch' 'Count Down Latch' 'Count Down Latch'
"M" 요청: countDownLatch.await();
서 " " "는 "T1", "T2", "T3"를 나타냅니다. countDownLatch.countdown();
조인 방식의 단점은 M이 T1, T2, T3에 대해 알아야 한다는 것입니다.나중에 새로운 워커 스레드 T4가 추가될 경우 M도 이를 인지해야 합니다.이는 Count Down Latch를 사용하여 회피할 수 있습니다.구현 후 액션의 순서는 [T1, T2, T3](T1, T2, T3의 순서는 어쨌든 가능) -> [M]가 됩니다.
이와 같은 것을 사용하는 경우의 좋은 예로는 Java Simple Serial Connector를 사용하여 시리얼 포트에 액세스하는 것이 있습니다.통상, 포토에 기입해, 다른 스레드상에서 비동기적으로 디바이스는 SerialPortEventListener 에 응답합니다.통상은, 포토에 기입한 후, 응답을 대기하기 위해서 일시 정지합니다.이 시나리오에서 스레드 잠금을 수동으로 처리하는 것은 매우 까다롭지만 카운트다운 래치를 사용하는 것은 쉽습니다.다른 방법으로 할 수 있다고 생각하기 전에, 생각지도 못했던 레이스 상황에 주의해 주세요!!
유사 코드:
CountDownLatch latch; void writeData() { latch = new CountDownLatch(1); serialPort.writeBytes(sb.toString().getBytes()) try { latch.await(4, TimeUnit.SECONDS); } catch (InterruptedException e) { } } class SerialPortReader implements SerialPortEventListener { public void serialEvent(SerialPortEvent event) { if(event.isRXCHAR()){//If data is available byte buffer[] = serialPort.readBytes(event.getEventValue()); latch.countDown(); } } }
호출 후에 latch.countDown()에 디버깅을 추가하면 동작을 이해하는 데 도움이 될 수 있습니다.
latch.countDown();
System.out.println("DONE "+this.latch); // Add this debug
출력에는 카운트가 감소하는 것이 표시됩니다.이 '카운트'는 실질적으로 countDown()이 호출되지 않은 실행 가능한 태스크(프로세서 개체)의 수이며, 따라서 latch.await()에 대한 호출로 메인 스레드가 차단됩니다.
DONE java.util.concurrent.CountDownLatch@70e69696[Count = 2]
DONE java.util.concurrent.CountDownLatch@70e69696[Count = 1]
DONE java.util.concurrent.CountDownLatch@70e69696[Count = 0]
CountDownLatch에 대한 Oracle 문서 참조:
다른 스레드에서 수행 중인 일련의 작업이 완료될 때까지 하나 이상의 스레드가 대기할 수 있는 동기화 보조 도구입니다.
A CountDownLatch
는 지정된 카운트로 초기화됩니다.await
는 메서드의 로 인해 이 될 합니다.countDown()
모든 대기 스레드가 해제되고 이후의 호출이 즉시 반환되는 메서드입니다.이것은 원샷 현상입니다.을 사용하다
Count Down Latch는 범용 동기화 도구이며 다양한 용도로 사용할 수 있습니다.
A CountDownLatch
카운트를 1로 초기화하면 단순한 on/off 래치 또는 게이트로 기능합니다.countDown()을 호출하는 스레드가 열릴 때까지 게이트에서 대기합니다.
A CountDownLatch
N으로 초기화된 경우 N개의 스레드가 일부 액션을 완료하거나 일부 액션이 N회 완료될 때까지 하나의 스레드를 대기시키는 데 사용할 수 있습니다.
public void await()
throws InterruptedException
스레드가 중단되지 않는 한 래치가 0까지 카운트다운될 때까지 현재 스레드가 대기합니다.
현재 카운트가 0일 경우 이 메서드는 즉시 반환됩니다.
public void countDown()
래치 카운트를 줄이고 카운트가 0에 도달하면 모든 대기 스레드를 해제합니다.
현재 카운트가 0보다 크면 감소합니다.새 카운트가 0인 경우 스레드 예약을 위해 모든 대기 스레드가 다시 활성화됩니다.
예에 대한 설명입니다.
했습니다.
latch
CountDownLatch latch = new CountDownLatch(3);
하셨습니다.
latch
스레드: " " " "Processor
- ★★★
Runnable
의Processor
ExecutorService
executor
스레드( 인인 ( ( main main main)
App
는, .아래 문장은 0입니다.latch.await();
Processor
sleep한 후 슬리브로 값을 .latch.countDown()
번째 번째
Process
후 는 완료 후 래치 카운트를 2로 변경합니다.latch.countDown()
.번째 ★★★
Process
후 합니다.는 1로 하다.latch.countDown()
번째 ★★★
Process
후 는 0이 되다.latch.countDown()
.카운트가 메인 0이 합니다.
App
에서 나오다await
은 지금합니다: 프음음음음음음음음음음음음음음음 app app app app app app app 。
Completed
Java Doc의 이 예는 개념을 명확하게 이해하는 데 도움이 되었습니다.
class Driver { // ...
void main() throws InterruptedException {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);
for (int i = 0; i < N; ++i) // create and start threads
new Thread(new Worker(startSignal, doneSignal)).start();
doSomethingElse(); // don't let run yet
startSignal.countDown(); // let all threads proceed
doSomethingElse();
doneSignal.await(); // wait for all to finish
}
}
class Worker implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
public void run() {
try {
startSignal.await();
doWork();
doneSignal.countDown();
} catch (InterruptedException ex) {} // return;
}
void doWork() { ... }
}
시각적 해석:
명히,는,CountDownLatch
의 스레드서는 1개의 스레드)를 합니다.Driver
Worker
을 사용하다
package practice;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch c= new CountDownLatch(3); // need to decrements the count (3) to zero by calling countDown() method so that main thread will wake up after calling await() method
Task t = new Task(c);
Task t1 = new Task(c);
Task t2 = new Task(c);
t.start();
t1.start();
t2.start();
c.await(); // when count becomes zero main thread will wake up
System.out.println("This will print after count down latch count become zero");
}
}
class Task extends Thread{
CountDownLatch c;
public Task(CountDownLatch c) {
this.c = c;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
c.countDown(); // each thread decrement the count by one
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
이 링크의 CountDownLatchExample에서 설명하는 countDownLatch의 최적의 실시간 예시
은 " " " 입니다.CyclicBarrier
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CountDownLatch.html에 따르면 다음을 참조하십시오.
CountDownLatch는 지정된 카운트로 초기화됩니다.wait 메서드는 countDown() 메서드의 호출로 인해 현재 카운트가 0이 될 때까지 차단합니다.그 후 모든 대기 스레드가 해방되고 이후의 모든 호출이 즉시 반환됩니다.이것은 원샷 현상입니다.카운트는 리셋 할 수 없습니다.카운트를 리셋하는 버전이 필요한 경우는, CyclicBarrier 의 사용을 검토해 주세요.
언급URL : https://stackoverflow.com/questions/17827022/how-is-countdownlatch-used-in-java-multithreading
'source' 카테고리의 다른 글
자바에서의 인터페이스와 @interface의 차이점은 무엇입니까? (0) | 2022.07.17 |
---|---|
nuxt 레이아웃 내에서 메서드를 실행하기 위한 vuex 상태 변경 감지 (0) | 2022.07.17 |
ld.exe: 출력 파일을 열 수 없습니다...: 권한이 거부되었습니다. (0) | 2022.07.17 |
C에서 1123456789에서 1,123,456,789까지의 숫자를 포맷하려면 어떻게 해야 합니까? (0) | 2022.07.17 |
nuxt.js Vuex Vuejs 정의되지 않은 속성 'getters'를 읽을 수 없습니다. (0) | 2022.07.17 |