文章目录
简介构造函数内部类countDown()await()示例
简介
CountDownLatch允许一个或者多个线程等待其它线程完成操作。
CountDownLatch 是通过一个计数器来实现的,当我们在 new 一个 CountDownLatch 对象的时候,需要带入该计数器值,该值就表示了线程的数量。
每当一个线程完成自己的任务后,计数器的值就会减 1 。当计数器的值变为0时,就表示所有的线程均已经完成了任务,然后就可以恢复等待的线程继续执行了。
CountDownLatch中只包含了Sync一个内部类,它没有公平/非公平模式。
构造函数
public CountDownLatch(int count
) {
if (count
< 0) throw new IllegalArgumentException("count < 0");
this.sync
= new Sync(count
);
}
内部类
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;
}
}
}
countDown()
public void countDown() {
sync
.releaseShared(1);
}
public final boolean releaseShared(int arg
) {
if (tryReleaseShared(arg
)) {
doReleaseShared();
return true;
}
return false;
}
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
);
}
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
;
failed
= false;
return;
}
}
if (shouldParkAfterFailedAcquire(p
, node
) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed
)
cancelAcquire(node
);
}
}
private void setHeadAndPropagate(Node node
, int propagate
) {
Node h
= head
;
setHead(node
);
if (propagate
> 0 || h
== null
|| h
.waitStatus
< 0 ||
(h
= head
) == null
|| h
.waitStatus
< 0) {
Node s
= node
.next
;
if (s
== null
|| s
.isShared())
doReleaseShared();
}
}
private void doReleaseShared() {
for (;;) {
Node h
= head
;
if (h
!= null
&& h
!= tail
) {
int ws
= h
.waitStatus
;
if (ws
== Node
.SIGNAL
) {
if (!compareAndSetWaitStatus(h
, Node
.SIGNAL
, 0))
continue;
unparkSuccessor(h
);
}
else if (ws
== 0 &&
!compareAndSetWaitStatus(h
, 0, Node
.PROPAGATE
))
continue;
}
if (h
== head
)
break;
}
}
示例
CountDownLatch 不仅能实现一个线程等待多个线程条件成立,还能实现多个线程等待一个线程条件成立。
public static void main(String
[] args
) throws InterruptedException
{
CountDownLatch startSignal
= new CountDownLatch(1);
CountDownLatch doneSignal
= new CountDownLatch(5);
for (int i
= 0; i
< 5; i
++) {
new Thread(()->{
try {
System
.out
.println(Thread
.currentThread().getName() + " 开始.");
startSignal
.await();
System
.out
.println(Thread
.currentThread().getName() + " 在干活.");
doneSignal
.countDown();
} catch (InterruptedException e
) {
e
.printStackTrace();
}
}).start();
}
Thread
.sleep(2000);
System
.out
.println("主线程开始.");
startSignal
.countDown();
System
.out
.println("主线程等待其它线程结束.");
doneSignal
.await();
System
.out
.println("其它线程已经结束,主线程开始做其它事情.");
}