juc包下的CountdownLatch

CountDownLatch

帮助一个或多个线程等待,直到其他线程中执行的操作都完成

CountDownLatch与给定数初始化。await直到当前计数达到零的countDown()方法调用,之后,所有等待的线程,释放任何后续的调用await立即返回。

CountDownLatch是一种通用的同步工具,可以用于许多用途。

 CountDownLatch latch=new CountDownLatch(2);
	    System.out.println("开始时间"+new Date());
	    Thread  thread1 = new Thread(new Runnable() {
			@Override
			public void run() {
				// TODO 自动生成的方法存根
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				 System.out.println("1号打螺丝完成时间"+new Date());
				System.out.println(" 我是1号程序员开始拧螺丝 ");
				latch.countDown();
			}
		});
	    Thread  thread2 = new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO 自动生成的方法存根
				
				try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				System.out.println("2号打螺丝完成时间"+new Date());
				System.out.println(" 我是2号程序员开始拧螺丝 ");
				latch.countDown();
			}
		});
	    thread1.start();
	    thread2.start();
	    latch.await();
	    System.out.println("结束时间"+new Date());

打印结果

在CountDownLatch类中,维护了一个内部类Sync,他继承了AQS,CoutDownLatch通过维护这个Sync,来实现所有功能

 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;
            }
        }
    }

构造方法

内部通过Sync这个类,来设置计数器的值

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

那这个state又是在哪呢?

看源码,是在AQS中维护了一个state,所以,实际上CountDownLatch的计数器,实际上就是AQS中的state

调用countDown方法,该方法委托给AQS来执行,先调用sync重写的tryRealeaseShared方法,

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;
    }
}

 true:此次释放资源的行为可能会让一个阻塞等待中的线程被唤醒

返回结果之后,实际通过doReleaseShared()方法来唤醒同步队列中的后续线程

如果返回false,则什么也不做

public void countDown() {
        sync.releaseShared(1); //调用aqs的方法
    }

// AQS的方法   实际调用的方法
 public final boolean releaseShared(int arg) {
       // tryReleaseShared(arg)实际走的是CountDownLatch下Sync这个内部类
        if (tryReleaseShared(arg)) {
            doReleaseShared();
            return true;
        }
        return false;
    }


await()让调用它的线程进行等待,直到所有CountDownLatch中的任务执行完成后,继续执行

可以看到实际走的是AQS的acquireSharedInterruptibly这个方法,

在这个方法中会通过Thread 的方法,进而判断线程是否中断,如果已经中断,直接抛出异常,如果在等待过程中,收到终端型哈哈,也会抛出中断异常,

所以await()会响应中断

 protected int tryAcquireShared(int acquires) {
            return (getState() == 0) ? 1 : -1;
        }
 public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);
    }


public final void acquireSharedInterruptibly(int arg)
            throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        if (tryAcquireShared(arg) < 0)
            doAcquireSharedInterruptibly(arg);
    }

CountDownLatch又和join有点相似

但事实上,内部实现还是有区别的

countDownLatch内部是通过AQS的双向链表,来维护等待线程,

Thread.join()是通过wait()阻塞当前线程,不断检查调用线程是否执行完毕,如果执行完毕会调用notifyAll()方法来唤醒当前线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

羊驼有点累

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值