1. 程式人生 > >對CountDownLatch的初步學習

對CountDownLatch的初步學習

nano jdk ive spec opera testing PE als AR

CountDownLatch的中文翻譯為"閉鎖",在JDK1.5中 CountDownLatch類加入進來。為程序猿進行並發編程提供有利的幫助。

首先我們先看看JDK文檔中對於CountDownLatch類的介紹:

A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
 大致意思是CountDownLatch為一個同步輔助工具,讓一個或多個線程等待,直到其他的線程執行操作完成。

  它的功能可以在絕大部分情況上替代join()方法,甚至在實際運用中比join()方法的用法更靈活。

  操作過程:用CountDownLatch類創建實例,指定需要等待完成點個數。await()方法會阻塞當前線程,直到計數器減為零。每次線程執行調用countDown()方法,就會使計數器減1,直到計數器減為0時,等待的線程繼續運行。

  • CountDownLatch類中的構造器:
    /**
     * 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
   * 構造器用給定計數作為參數進行初始化,若參數為負則拋出非法參數異常。
   *
*/ public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); }

  • CountDownLatch類中的方法:

  1. await() 方法

    /**
     * Causes the current thread to wait until the latch has counted down to
     * zero, unless the thread is {@linkplain Thread#interrupt interrupted}.
     * 使當前線程等待直到閉鎖的計數器為0,除非線程由於中斷異常中斷。
     */
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

  2. await(long timeout, TimeUnit unit) 方法

    /**
     * Causes the current thread to wait until the latch has counted down to
     * zero, unless the thread is {@linkplain Thread#interrupt interrupted},
     * or the specified waiting time elapses.
   * 使當前線程等待直到閉鎖計數器為0,除非線程遇到線程中斷異常中斷,或者超出指定的等待時間。 * @param timeout the maximum time to wait 超出的最大等待時間 * @param unit the time unit of the {@code timeout} argument 指定最大等待時間的時間單位 * @return {@code true} if the count reached zero and {@code false} * if the waiting time elapsed before the count reached zero * @throws InterruptedException if the current thread is interrupted * while waiting */ public boolean await(long timeout, TimeUnit unit) throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); }

  3. countDown() 方法

    /**
     * Decrements the count of the latch, releasing all waiting threads if
     * the count reaches zero.
     * 減少閉鎖的計數,若計數達到0則釋放所有等待線程
     * <p>If the current count is greater than zero then it is decremented.
     * If the new count is zero then all waiting threads are re-enabled for
     * thread scheduling purposes.
     *
     * <p>If the current count equals zero then nothing happens.
     */
    public void countDown() {
        sync.releaseShared(1);
    }

  4. getCount() 方法

    /**
     * Returns the current count.
     * 返回當前計數器的值
     * <p>This method is typically used for debugging and testing purposes.
     *
     * @return the current count
     */
    public long getCount() {
        return sync.getCount();
    }

應用:

  有這麽一道題:用4個線程並發執行從1加到100,每個線程只能加25個數,主線程需要等待子線程結束完成後才能結束。

  思想:可以用join()方法,也可以用CountDownLatch對象來暫停主線程。

  代碼:

import java.util.concurrent.CountDownLatch;

public class Compute {
    public static int sum = 0;// 存儲1加到100的數
    public static CountDownLatch count = new CountDownLatch(4);// 閉鎖,計數器設置為4

    static class ComputeThread extends Thread {// 內部類
        int start, end;// 起始與結束

        public ComputeThread(int start, int end) {
            this.start = start;
            this.end = end;
        }

        @Override
        public void run() {// 每個線程都進行累加
            for (int i = start; i <= end; i++) {
                sum += i;
            }
            System.out.println(currentThread().getName() + ":" + sum);
            count.countDown();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 建立4個線程
        ComputeThread c1 = new Compute.ComputeThread(1, 25);
        ComputeThread c2 = new Compute.ComputeThread(26, 50);
        ComputeThread c3 = new Compute.ComputeThread(51, 75);
        ComputeThread c4 = new Compute.ComputeThread(76, 100);
        // 啟動4個線程
        c1.start();
        c2.start();
        c3.start();
        c4.start();
        // 讓調用線程停止,等待計數器為0
        count.await();
        System.out.println(sum);
    }
}
 

對CountDownLatch的初步學習