abstractqueuedsynchronizer详解(二)——countdownlatch源码分析_第1页
abstractqueuedsynchronizer详解(二)——countdownlatch源码分析_第2页
abstractqueuedsynchronizer详解(二)——countdownlatch源码分析_第3页
abstractqueuedsynchronizer详解(二)——countdownlatch源码分析_第4页
abstractqueuedsynchronizer详解(二)——countdownlatch源码分析_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

AbstractQueuedSynchronizer 详解(二) CountDownLatch 源码分析 CountDownLatch 的使用 CountDownLatch 是一个工具类,用于使一个或多个线程等待另一系列线程完成操作,也就 是说一些线程在另外一些完成之后才能继续执行,类似线性。 初始 CountDownLatch 时需要提供一个 count 参数,await 方法将会使线程阻塞,直到这个 值变为 0,countDown()方法可以使 count 值减 1,一旦到达 0 后,调用 await 阻塞的线程将 会得到释放。 CountDown 一般有两个用法。 一个线程等待多个线程 一个线程等待多个线程完成后再执行,比如一个不限时的考试,10 个学生考试,交卷时间 不同,当 10 个学生都交卷后,老师才认为考试结束。下面是该例子: public class ExamDemo public static class Student implements Runnable private int num;/学号 private CountDownLatch countDownLatch; public Student(int num, CountDownLatch countDownLatch) this.num = um; this.countDownLatch = countDownLatch; Override public void run() Random random = new Random(); try TimeUnit.SECONDS.sleep(random.nextInt(10) + 1); catch (InterruptedException e) e.printStackTrace(); System.out.println(“学生“ + num + “交卷了“); /完成工作,将 count-1 countDownLatch.countDown(); public static class Teacher implements Runnable private CountDownLatch countDownLatch; public Teacher(CountDownLatch countDownLatch) this.countDownLatch = countDownLatch; Override public void run() System.out.println(“考试开始,不限时间!“); try /等待 count 变为 0 countDownLatch.await(); catch (InterruptedException e) e.printStackTrace(); System.out.println(“考试结束“); public static void main(String args) Executor executor = Executors.newCachedThreadPool(); CountDownLatch countDownLatch = new CountDownLatch(10); executor.execute(new Teacher(countDownLatch); for (int i = 1; i = 0) setHeadAndPropagate(node, r); p.next = null; / help GC failed = false; return; /检查是否需要将当前线程挂起 if (shouldParkAfterFailedAcquire(p, node) finally if (failed) cancelAcquire(node); 队列的结构如下: 其中 Head 是个空节点,所以一旦前驱节点是头节点,并且要是 count 变为了 0,那么就调 用 setHeadAndPropagate 方法,然后释放头节点。 setHeadAndPropagate 方法主要完成两件 事,第一更改头节点,第二由于此时等待线程可以执行了,将该事件传播给后面的节点, 实现如下: private void setHeadAndPropagate(Node node, int propagate) Node h = head; / Record old head for check below /更改头节点 setHead(node); /* * Try to signal next queued node if: * Propagation was indicated by caller, * or was recorded (as h.waitStatus either before * or after setHead) by a previous operation * (note: this uses sign-check of waitStatus because * PROPAGATE status may transition to SIGNAL.) * and * The next node is waiting in shared mode, * or we dont know, because it appears null * * The conservatism in both of these checks may cause * unnecessary wake-ups, but only when there are multiple * racing acquires/releases, so most need signals now or soon * anyway. */ /如果需要传播 if (propagate 0 | h = null | h.waitStatus 0 | (h = head) = null | h.waitStatus 0) Node s = de.next; if (s = null | s.isShared() doReleaseShared(); 可以看到如果需要传播的话,将会调用 doReleasShared 方法 ,方法如下: private void doReleaseShared() for (;) Node h = head; if (h != null if (ws = Node.SIGNAL) if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0) /重置状态,成功 后,将后继节点唤醒 continue; / loop to recheck cases unparkSuccessor(h); else if (ws = 0 / loop on failed CAS if (h = head) / loop if head changed break; 至此,await 方法就使线程挂起了,下面再分析 countDown 方法。 countDown 方法 countDown 方法用于将 count 值减 1,如果 count 变为 0 则释放所有等待线程,方法的实现如 下: public void countDown() sync.releaseShared(1); releaseShared 方法如下 : public final boolean releaseShared(int arg) /尝试释放共享资源,如果需要释放节点,则释放节点 if (tryReleaseShared(arg) doReleaseShared(); return true; return false; tryReleaseShared 需要在子类中实现,Sync 中的实现如下: 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; 一开始设置了 count,每次 countDown 会使 AQS 的 state-1,一旦变成 0,则返回 true。而 如果变成了 0 后,又调用 countDown 则无效。doReleaseShared 方法用于释

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论