1 CountDownLatch
CountDownLatch.Sync繼承了AbstractQueuedSynchronizer悔据,重寫了tryAcquireShared方法和tryReleaseShared方法省古。
public class CountDownLatch {
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) {
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
private final Sync sync;
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
public void countDown() {
sync.releaseShared(1);
}
public long getCount() {
return sync.getCount();
}
public String toString() {
return super.toString() + "[Count = " + sync.getCount() + "]";
}
}
2 CountDownLatch圖解
state大于0時(shí),所有調(diào)用了await方法的線程都會(huì)被阻塞;state等于0時(shí),所有被阻塞的線程一起通過柵欄。
3 CountDownLatch使用案例1
3.1 Driver
public class Driver1 {
public static void main(String[] args) {
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(10);
for (int i = 0; i < 10; i++)
new Thread(new Worker1(startSignal, doneSignal)).start();
sleep(1);
System.out.println("開始執(zhí)行任務(wù)");
startSignal.countDown();
try {
doneSignal.await();
System.out.println("已完成所有任務(wù)");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void sleep(int second) {
try {
TimeUnit.SECONDS.sleep(second);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.2 Worker
public class Worker1 implements Runnable {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
public Worker1(CountDownLatch startSignal, CountDownLatch doneSignal) {
super();
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}
@Override
public void run() {
try {
startSignal.await();
doWork();
doneSignal.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
void doWork() {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + ": 已完成任務(wù)");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
4 CountDownLatch使用案例2
4.1 Driver
public class Driver2 {
public static void main(String[] args) {
CountDownLatch doneSignal = new CountDownLatch(10);
Executor e = Executors.newFixedThreadPool(5);
for (int i = 1; i <= 10; i++)
e.execute(new Worker2(doneSignal, i));
try {
doneSignal.await();
System.out.println("已完成所有任務(wù)");
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
4.2 Worker
public class Worker2 implements Runnable {
private final CountDownLatch doneSignal;
private final int i;
Worker2(CountDownLatch doneSignal, int i) {
this.doneSignal = doneSignal;
this.i = i;
}
@Override
public void run() {
doWork(i);
doneSignal.countDown();
}
void doWork(int i) {
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + ": 已完成第" + i + "項(xiàng)任務(wù)");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}