CountDownLatch使用
CountDownLatch結合多執行緒可以控制併發,非同步先行,併發阻塞,充分利用多核cpu,同時處理多項事情,底層實現是sync、volatile 來做執行緒可見性。
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * CountDownLatch中文翻譯 倒計時門閂(shuan) * CountDownLatch可以控制併發,非同步先行,同步等待,充分利用多核cpu,同時處理多項事情,底層實現是sync、volatile 來做執行緒可見性 * The synchronization state. * private volatile int state; * */ public class CountDownLatchTest { public static final Logger logger = LoggerFactory.getLogger(CountDownLatchTest.class); public static void main(String[] args) throws InterruptedException { /** * Constructs a {@code CountDownLatch} initialized with the given count. * * @param count the number of times {@link #countDown} must be invoked *before threads can pass through {@link #await} * @throws IllegalArgumentException if {@code count} is negative */ //初始化5個count數,也就是說有5把鎖,為負數則丟擲IllegalArgumentException final CountDownLatch countDownLatch = new CountDownLatch(5); /** * Creates a thread pool that reuses a fixed number of threads * operating off a shared unbounded queue.At any point, at most * {@code nThreads} threads will be active processing tasks. * If additional tasks are submitted when all threads are active, * they will wait in the queue until a thread is available. * If any thread terminates due to a failure during execution * prior to shutdown, a new one will take its place if needed to * execute subsequent tasks.The threads in the pool will exist * until it is explicitly {@link ExecutorService#shutdown shutdown}. * * @param nThreads the number of threads in the pool * @return the newly created thread pool * @throws IllegalArgumentException if {@code nThreads <= 0} */ //建立一個固定5個執行緒數量的執行緒池 ExecutorService executorService = Executors.newFixedThreadPool(5); //模擬5次請求 for (int i = 0; i < 5; i++) { //併發執行 executorService.execute(() -> { logger.info(Thread.currentThread().getName() + "準備解鎖"); //開始解鎖,每執行一次,解除一把鎖 countDownLatch.countDown(); logger.info(Thread.currentThread().getName() + "已解鎖"); }); } logger.info("等待解鎖中..."); //當鎖的數量不為0時,一直在這裡阻塞 countDownLatch.await(); logger.info("全部釋放,任務執行完成,開始執行後續動作..."); //關閉執行緒池 executorService.shutdown(); } }
日誌輸出:
18:29:58.585 [main] INFO com.test.tenant.CountDownLatchTest - 等待解鎖中... 18:29:58.584 [pool-1-thread-2] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-2準備解鎖 18:29:58.585 [pool-1-thread-1] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-1準備解鎖 18:29:58.588 [pool-1-thread-2] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-2已解鎖 18:29:58.585 [pool-1-thread-3] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-3準備解鎖 18:29:58.584 [pool-1-thread-5] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-5準備解鎖 18:29:58.588 [pool-1-thread-3] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-3已解鎖 18:29:58.588 [pool-1-thread-5] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-5已解鎖 18:29:58.588 [pool-1-thread-1] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-1已解鎖 18:29:58.584 [pool-1-thread-4] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-4準備解鎖 18:29:58.588 [pool-1-thread-4] INFO com.test.tenant.CountDownLatchTest - pool-1-thread-4已解鎖 18:29:58.588 [main] INFO com.test.tenant.CountDownLatchTest - 全部釋放,任務執行完成,開始執行後續動作... Process finished with exit code 0