1,概述
java并发包已经讲解了volatile,synchronized,CAS,AQS机制等。这些都是整个并发的基础,这篇主要讲一下并发包下的一些组件。
2,CountDownLatch
2.1 demo:
首先演示下这个组件的功能。主线程执行到await()方法后,就会同步等待2个线程执行,这里的2就是构造函数传入的。然后再执行下去。
public class CountDownLatchDemo { public static void main(String[] args) throws Exception{ final CountDownLatch latch = new CountDownLatch(2); new Thread() { @Override public void run() { try { Thread.sleep(1000); System.out.println("线程1执行..."); latch.countDown(); } catch (Exception e) { e.printStackTrace(); } } }.start(); new Thread() { @Override public void run() { try { Thread.sleep(1000); System.out.println("线程2执行..."); latch.countDown(); } catch (Exception e) { e.printStackTrace(); } } }.start(); System.out.println("主线程即将执行await..."); latch.await(); System.out.println("主线程执行..."); } }
2.2 构造函数:
public CountDownLatch(int count) { if (count < 0) throw new IllegalArgumentException("count < 0"); this.sync = new Sync(count); } //将传入的参数作为state的大小。这里的state即AQS下的state Sync(int count) { setState(count); }
2.3 await():
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); }
这里需要看看tryAcquireShared()方法:
protected int tryAcquireShared(int acquires) { return (getState() == 0) ? 1 : -1; }
很明显,state是我们传入的2,不等于0,会进入方法doAcquireSharedInterruptibly():
private void doAcquireSharedInterruptibly(int arg) throws InterruptedException { final Node node = addWaiter(Node.SHARED); boolean failed = true; try { for (;;) { final Node p = node.predecessor(); if (p == head) { int r = tryAcquireShared(arg); if (r >= 0) { setHeadAndPropagate(node, r); p.next = null; // help GC failed = false; return; } } if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) throw new InterruptedException(); } } finally { if (failed) cancelAcquire(node); } }
这个方法前面都分析过,直接画图了:
然后其他线程会执行countDown()方法,源码逻辑很简单,就是依次去减state的值。然后判断state是否等于0,如果state==0,则唤醒队列中main线程。可以发现,熟悉AQS原理之后,这些都是很简单的,所以AQS是并发的基础。