CountDownLatch
는 멀티 스레드 환경에서 이전 스레드의 실행이 끝날 때까지 여러 스레드가 대기할 수 있도록 하는 멀티 스레드 동기화 도구 클래스입니다. 클래스 이름으로 보아 CountDown
은 숫자를 감소시킨다는 의미이므로 카운터로 이해하면 됩니다. CountDownLatch
是一个多线程同步工具类,在多线程环境中它允许多个线程处于等待状态,直到前面的线程执行结束。从类名上看CountDown
既是数量递减的意思,我们可以把它理解为计数器。
countDown()
:计数器递减方法。
await()
:使调用此方法的线程进入等待状态,直到计数器计数为0时主线程才会被唤醒。
await(long, TimeUnit)
:在await()
方法的基础上增加了超时策略,若等待超时仍未有结果则会直接唤醒主线程运行。
在这里我们用一段简单的代码进行演示:
@Slf4j public class CountDownLatchDemo { public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); new Thread(() -> { log.info("hello this is thread one"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } countDownLatch.countDown(); }).start(); new Thread(() -> { log.info("hello this is thread two"); countDownLatch.countDown(); }).start(); new Thread(() -> { log.info("hello this is thread three"); countDownLatch.countDown(); }).start(); countDownLatch.await(); log.info("say good bye!"); } }
由上面的代码可见,我们创建了一个CountDownLatch
计数器为3和三个线程同步运行。在main主线程中调用了countDownLatch.await()
方法使主线程进入阻塞。其中三个线程任务执行完毕后都会调用countDownLatch.countDown()
方法对计数器进行递减,当三个线程任务都执行完毕后计数器计数值为0时主线程被唤醒。
注:在创建
CountDownLatch
实例时必须定义计数器值,一般相对较合理的用法是该值的定义需要经过合理的计算使计数值与需要并行的线程数相等,在每个线程执行完成后做计数递减,最终唤醒主线程继续执行。
CountDownLatch
计数值设置大于线程数,那么最终所有线程都执行完了,而计数为递减到0那么主线程将会一直处于等待状态。
CountDownLatch
计数值设置小于并发线程数,那么可能在部分线程未执行完毕时,计数就已经递减到0,则主线程会被提前唤醒。
如下图,主线程阻塞与唤醒的核心就是计数器,只有当所有线程执行完成计数逐个递减最终才会唤起await()
阻塞中的主线程。
注:
await()
可以阻塞一个线程,也可以阻塞多个线程,如果是阻塞多个线程,那么在计数为0时将会唤醒所有被阻塞的线程。
在简单了解完CountDownLatch
的作用后,相信各位最终目的还是想了解如何去使用,在哪些场景下使用更加合适,接下来我就拿一个对账业务的场景详细分析一下。
在当前的情况下,许多平台会与银联、微信、支付宝等支付渠道对接交易,因此无法避免进行对账。对账通常都会在每日的凌晨去处理,一方面是凌晨时间点多数平台访问量都会较小,服务器压力也比较轻松,而且此时出账也比较合理,所以在这个时间点做对账也是一个大数据量计算的操作。
上面讲这么多好像都没说到重点,在处理对账之前首先我们肯定是需要通过各个支付渠道获取对账单文件,那么该如何操作呢?
对账文件下载(第一阶段):在这种情况下可以设计三个任务并发去获取对账文件,使用CountDownLatch
阻塞主线程,等待三个任务都获取到文件的时候做计数递减,最终唤醒主线将标记本阶段处理完成,并发起进入下一阶段的通知。
对账文件解析(第二阶段):在上个阶段已下载完成的文件文件中,此阶段要做的就是解析文件。由于三个渠道都是不同的厂家那么文件的内容格式肯定都是不一样的,这时候我们又可以使用CountDownLatch
countDown()
: 카운터 감소 메서드. 🎜await()
: 이 메서드를 호출하는 스레드를 대기 상태로 전환합니다. 카운터가 0이 될 때까지 기본 스레드는 깨어나지 않습니다. 🎜await(long, TimeUnit)
: 대기 후 결과가 없는 경우 await()
메서드를 기반으로 시간 초과 전략이 추가됩니다. 시간 초과의 경우 실행을 위해 메인 스레드를 직접 깨울 것입니다. 🎜countDownLatch.await()
메서드는 메인 스레드에서 호출되어 메인 스레드를 차단합니다. 세 개의 스레드 작업이 실행된 후 countDownLatch.countDown()
메서드가 호출되어 카운터를 감소시킵니다. 세 개의 스레드 작업이 모두 실행되면 카운터 값이 0에 도달하고 기본 스레드가 활성화됩니다. 🎜🎜참고: CountDownLatch
인스턴스를 생성할 때 카운터 값을 정의해야 합니다. 일반적으로 값을 정의하려면 합리적인 계산이 필요하다는 것이 상대적으로 합리적인 사용법입니다. 카운트 값을 병렬화해야 하는 스레드 수와 동일하게 만듭니다. 각 스레드의 실행이 완료된 후 카운트가 감소하고 마지막으로 메인 스레드가 깨어나 실행을 계속합니다. 🎜
CountDownLatch
카운트 값이 스레드 수보다 크게 설정되면 결국 모든 스레드가 실행되고 횟수가 0으로 감소합니다. 그러면 메인 스레드는 항상 대기 상태에 있게 됩니다. 🎜CountDownLatch
카운트 값이 동시 스레드 수보다 작게 설정된 경우 일부 스레드가 실행을 완료하기 전에 카운트가 0으로 감소했을 수 있으며, 메인 스레드는 일찍 깨어납니다. 🎜await()
메인 스레드가 차단되었습니다. 🎜🎜참고: await()
는 하나의 스레드 또는 여러 스레드를 차단할 수 있습니다. 여러 스레드가 차단되면 개수가 0이 되면 깨어납니다. 차단된 모든 스레드. 🎜
🎜 🎜🎜시나리오 활용🎜🎜CountDownLatch
의 기능을 간략히 이해한 후, 이를 어떻게 사용하는지, 어떤 시나리오에 사용하는 것이 더 적합한지 이해하는 것이 최종 목표라고 생각합니다. 다음 , 화해 사업을 맡겠습니다. 시나리오를 자세히 분석해 보겠습니다. 🎜🎜현재 상황에서는 많은 플랫폼이 UnionPay, WeChat, Alipay 등 결제 채널과 거래를 연결하므로 화해가 불가피합니다. 조정은 일반적으로 매일 이른 아침에 처리됩니다. 한편, 대부분의 플랫폼은 이른 아침 시간에 방문 수가 적고 서버 압력이 상대적으로 완화되어 있으며 이때 계정이 더 합리적이므로 또한 그렇습니다. 이때 조정을 수행하는 데 적합합니다. 대용량 데이터 계산 작업입니다. 🎜🎜위에 언급된 사항 중 어느 것도 언급되지 않은 것 같습니다. 화해를 처리하기 전에 먼저 다양한 결제 채널을 통해 명세서 파일을 받아야 합니다. 그러면 어떻게 운영해야 할까요? 🎜CountDownLatch
를 사용하여 세 개의 스레드를 시작하여 해당 조정 파일을 구문 분석할 수 있습니다. 업무에 필요한 통일된 형식의 데이터로 변환되어 데이터베이스에 저장되며, 세 가지 작업이 모두 데이터베이스에 저장된 후 메인 스레드가 깨어나 완료로 표시되어 다음 단계의 작업 시작을 알립니다. 🎜화해 및 정산(3단계): 이전 단계의 데이터가 데이터베이스에 입력된 후 이 단계에서 수행해야 할 작업은 일반적으로 주문 번호와 거래 채널에서 거래 금액이 일치하는지 확인하세요. 금액이 일치하면 거래가 성공적으로 처리됩니다. 그렇지 않으면 해당 거래는 비정상적인 거래로 간주되어 데이터베이스에 저장됩니다. 위의 프로세스 분석을 바탕으로 동시성을 제어하고 비교 트랜잭션 주문을 동시에 처리하는 비교적 합리적인 CountDownLatch
计数,结合Semaphore
세마포를 설계할 수 있습니다. 마지막으로 모든 트랜잭션 주문이 처리된 후 메인 스레드가 활성화되어 조정을 표시하고 다음을 알립니다. 계정을 진행하는 단계입니다.
계좌 발행(4단계): 일반적으로 플랫폼은 조정이 완료된 후 계좌를 발행합니다. 즉, 금융 담당자가 통계를 작성할 수 있도록 플랫폼의 업무 규칙에 따라 관련 청구서를 발행합니다. .
위 내용은 Java 다중 스레드 동기화 도구 클래스 CountDownLatch를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!