Java并发教程– CountDownLatch
其他實(shí)用程序不太常見(jiàn),因此有時(shí)它們可??能會(huì)使我們逃脫,但是請(qǐng)記住它們是很好的。 CountDownLatch是這些工具之一。
CountDownLatch –更通用的等待/通知機(jī)制
各種Java開(kāi)發(fā)人員都應(yīng)該熟悉等待/通知方法,直到達(dá)到條件為止。 以下是有關(guān)其工作原理的一些示例:
public void testWaitNotify() throws Exception {final Object mutex = new Object();Thread t = new Thread() {public void run() {// we must acquire the lock before waiting to be notifiedsynchronized(mutex) {System.out.println("Going to wait " +"(lock held by " + Thread.currentThread().getName() + ")");try {mutex.wait(); // this will release the lock to be notified (optional timeout can be supplied)} catch (InterruptedException e) {e.printStackTrace();} System.out.println("Done waiting " +"(lock held by " + Thread.currentThread().getName() + ")");}}};t.start(); // start her up and let her wait()// not normally how we do things, but good enough for demonstration purposesThread.sleep(1000);// we acquire the lock released by wait(), and notify()synchronized (mutex) {System.out.println("Going to notify " +"(lock held by " + Thread.currentThread().getName() + ")");mutex.notify();System.out.println("Done notify " +"(lock held by " + Thread.currentThread().getName() + ")");}}輸出量
Going to wait (lock held by Thread-0) Going to notify (lock held by main) Done notify (lock held by main) Done waiting (lock held by Thread-0)實(shí)際上, CountDownLatch可以類似于等待/通知,僅使用一個(gè)通知即可使用-也就是說(shuō),只要您不希望在獲取鎖并調(diào)用wait()之前調(diào)用notify()時(shí), wait()就會(huì)停頓。 。 因此,它實(shí)際上是更寬容的,在某些情況下,這正是您想要的。 這是一個(gè)示例:
public void testWaitNotify() throws Exception {final CountDownLatch latch = new CountDownLatch(1); // just one timeThread t = new Thread() {public void run() {// no lock to acquire!System.out.println("Going to count down...");latch.countDown();}};t.start(); // start her up and let her wait()System.out.println("Going to await...");latch.await();System.out.println("Done waiting!"); }如您所見(jiàn),它比等待/通知更簡(jiǎn)單,并且所需的代碼更少。 它還允許我們?cè)谡{(diào)用wait()之前調(diào)用最終釋放該塊的條件。 這可能意味著代碼更安全。
真實(shí)的例子
因此我們知道我們可以將其用作更簡(jiǎn)單的等待/通知機(jī)制,但是您可能已經(jīng)在上面看到了構(gòu)造函數(shù)參數(shù)。 在構(gòu)造函數(shù)中,指定解鎖之前需要遞減鎖存器的次數(shù)。 有什么可能的用途? 好吧,它可以使進(jìn)程等待直到采取了一定數(shù)量的動(dòng)作。
例如,如果您具有可以通過(guò)偵聽(tīng)器或類似方法掛接到的異步進(jìn)程,則可以創(chuàng)建單元測(cè)試以驗(yàn)證是否進(jìn)行了一定數(shù)量的調(diào)用。 這使我們只需要在正常情況下需要的時(shí)間(或在保釋并假設(shè)失敗之前的某個(gè)限制)即可。
最近,我遇到了一種情況,我必須驗(yàn)證是否已將JMS消息從隊(duì)列中拉出并正確處理。 這自然是異步的,并且不在我的控制范圍之內(nèi),并且也不選擇模擬,因?yàn)樗蔷哂蠸pring上下文的完全組裝的應(yīng)用程序,等等。為了測(cè)試這一點(diǎn),我對(duì)使用服務(wù)進(jìn)行了微小的更改,以允許在郵件已處理。 然后,我可以臨時(shí)添加一個(gè)偵聽(tīng)器,該偵聽(tīng)器使用CountDownLatch保持測(cè)試盡可能接近同步。
這是顯示概念的示例:
public void testSomeProcessing() throws Exception {// should be called twicefinal CountDownLatch testLatch = new CountDownLatch(2);ExecutorService executor = Executors.newFixedThreadPool(1);AsyncProcessor processor = new AsyncProcessor(new Observer() {// this observer would be the analogue for a listener in your async processpublic void update(Observable o, Object arg) {System.out.println("Counting down...");testLatch.countDown();}});//submit two tasks to be process// (in my real world example, these were JMS messages)executor.submit(processor);executor.submit(processor);System.out.println("Submitted tasks. Time to wait...");long time = System.currentTimeMillis();testLatch.await(5000, TimeUnit.MILLISECONDS); // bail after a reasonable timelong totalTime = System.currentTimeMillis() - time;System.out.println("I awaited for " + totalTime +"ms. Did latch count down? " + (testLatch.getCount() == 0));executor.shutdown(); }// just a process that takes a random amount of time // (up to 2 seconds) and calls its listener public class AsyncProcessor implements Callable<Object> {private Observer listener;private AsyncProcessor(Observer listener) {this.listener = listener;}public Object call() throws Exception {// some processing here which can take all kinds of time...int sleepTime = new Random().nextInt(2000);System.out.println("Sleeping for " + sleepTime + "ms");Thread.sleep(sleepTime);listener.update(null, null); // not standard usage, but good for a demoreturn null;} }輸出量
Submitted tasks. Time to wait... Sleeping for 739ms Counting down... Sleeping for 1742ms Counting down... I awaited for 2481ms. Did latch count down? true結(jié)論
CountDownLatch就是這樣。 它不是一個(gè)復(fù)雜的主題,而且用途有限,但是當(dāng)您遇到類似我的問(wèn)題時(shí),很高興看到示例并知道它們?cè)谀墓ぞ呦渲小?將來(lái),如果沒(méi)有其他問(wèn)題,我一定會(huì)牢記這一點(diǎn),以便進(jìn)行更簡(jiǎn)單的等待/通知。 如果您對(duì)此帖子或系列中的其他帖子有疑問(wèn)或評(píng)論,請(qǐng)留言。
參考:來(lái)自Carfey Software博客的 JCG合作伙伴的Java并發(fā)第6部分– CountDownLatch 。
相關(guān)文章 :- Java并發(fā)教程–信號(hào)量
- Java并發(fā)教程–重入鎖
- Java并發(fā)教程–線程池
- Java并發(fā)教程–可調(diào)用,將來(lái)
- Java并發(fā)教程–阻塞隊(duì)列
- Exchanger和無(wú)GC的Java
- Java Fork / Join進(jìn)行并行編程
- 使用迭代器時(shí)如何避免ConcurrentModificationException
- 改善Java應(yīng)用程序性能的快速技巧
翻譯自: https://www.javacodegeeks.com/2011/09/java-concurrency-tutorial.html
總結(jié)
以上是生活随笔為你收集整理的Java并发教程– CountDownLatch的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 将MongoDB与Morphia结合使用
- 下一篇: Java日志混乱