1. 程式人生 > 實用技巧 >openstack 本地yum源搭建

openstack 本地yum源搭建

一 使用場景

  在網上找了個例子,這個例子很好地說明了CountDownLatch 的用法,概括地說就是主執行緒等待子執行緒執行完了,主執行緒接著執行

public class CountDownLatchTest {

    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(2);
        System.out.println("主執行緒開始執行…… ……");
        //第一個子執行緒執行
        ExecutorService es1 = Executors.newSingleThreadExecutor();
        es1.execute(
new Runnable() { @Override public void run() { try { Thread.sleep(3000); System.out.println("子執行緒:"+Thread.currentThread().getName()+"執行"); } catch (InterruptedException e) { e.printStackTrace(); } latch.countDown(); } }); es1.shutdown();
//第二個子執行緒執行 ExecutorService es2 = Executors.newSingleThreadExecutor(); es2.execute(new Runnable() { @Override public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(
"子執行緒:"+Thread.currentThread().getName()+"執行"); latch.countDown(); } }); es2.shutdown(); System.out.println("等待兩個執行緒執行完畢…… ……"); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("兩個子執行緒都執行完畢,繼續執行主執行緒"); } }

二 程式碼概況

  CountDownLatch的功能都是通過內部實現AQS來實現的

private static final class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }

    private final Sync sync;

CountDownLatch的構造方法如下

public CountDownLatch(int count) {
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

使用者傳進去的count就賦值給AQS的state

三 await原始碼分析

public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }

  之前分析過共享鎖的程式碼,共享鎖的主要邏輯還是要看使用者實現的tryAcquireShared

protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }

如果state不是0的話,返回-1,這樣主執行緒就會進到佇列中排隊,並把自己阻塞起來,只能等待其他執行緒的喚醒

四 CountDown原始碼分析

每次呼叫countDown() 固定是釋放一個共享資源

 public void countDown() {
        sync.releaseShared(1);
    }
protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)//如果已經是0,那就沒法釋放了,返回false,這樣就不會執行unpark方法
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))//減一成功後比較state是不是0,如果返回true
                    return nextc == 0;
            }
        }

如果state == 0,那麼tryReleaseShared返回true,這樣就會執行unpark的邏輯,這樣主執行緒被喚醒,程式碼就可以繼續執行了

五 總結

  CountDownLatch的原始碼不多,邏輯也不復雜,但是可以很好的看看如果通過繼承AQS實現自己的邏輯。