源码解析:
CountDownLatch:委托给sync(AQS);
CountDown是一个共享锁。
回忆之前的例子:就是多个线程每个线程求自己的和,求完之后就down,最后再加和。
共享锁实现的方法。
---------------------
看下这个方法:
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
是谁调用的这个呢?
这里:
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
点进去sync.acquireSharedInterruptibly(1)
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);//传的1tryAc之后事<0的,然后就放在等待队列
}
这里调用的。tryAcquireShared(arg) < 0就不去管了,放在等待队列里面。其他的不执行。
细节:https://blog.csdn.net/mazhimazh/article/details/19190241
----再看
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;
}
}
也是判断状态的。
------------------------------------------------------------------------------------------------------------------------
CyclicBarrier源码:场景就是计数值为给定的值,所有进入await的方法进行执行,计数值-1,为0所有的线程唤醒。
看下构造方法:
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;//开会
}
barrierAction这个传入的是都到齐了要干什么事?
找到await方法:
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
dowait是核心:
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;//加锁
lock.lock();
try {
final Generation g = generation;//支持重置的
if (g.broken)
throw new BrokenBarrierException();
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
}
int index = --count;//等待的线程数少了一个
if (index == 0) { // tripped 为0叫醒所有的
boolean ranAction = false;
try {
final Runnable command = barrierCommand;//做的动作开会
if (command != null)
command.run();
ranAction = true;
nextGeneration();//在这里叫醒所有
return 0;//回到原始状态
} finally {
if (!ranAction)
breakBarrier();//执行run方法出现异常则打破屏障
}
}
// loop until tripped, broken, interrupted, or timed out
//10个线程第三个进来了
for (;;) {
try {
if (!timed)
trip.await();//等待
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {//中断了
if (g == generation && ! g.broken) {
breakBarrier();//根据条件打破中断叫醒
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
}
if (g.broken)//这些事等待之后被叫醒才执行的 这个事可以在线程传递的
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
看这个方法nextGeneration();
private void nextGeneration() {
// signal completion of last generation
trip.signalAll();//叫醒
// set up next generation
count = parties;//重置
generation = new Generation();//置为false,没有中断
}
打破屏障
private void breakBarrier() {
generation.broken = true;//置为true,这个是可以在线程传递的
count = parties;//初始化
trip.signalAll();//叫醒
}
写代码测试下:
我们随便找个线程进行中断。
package com.roocon.thread.tb5;
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
public class DemoMy {
Random random = new Random();
public void meeting(CyclicBarrier barrier) {
try {
Thread.sleep(random.nextInt(4000));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " arrive meetroom wait..");
if(Thread.currentThread().getName().equals("Thread-7")) {
Thread.currentThread().interrupt();
}
try {
barrier.await();//2.在这里await
System.out.println(Thread.currentThread().getName() + " arrive meetroom wait end..");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
DemoMy demo = new DemoMy();
CyclicBarrier barrier = new CyclicBarrier(10, new Runnable() {//0.new一个barrier
@Override
public void run() {
System.out.println("ok! begin meeting...");
}
});
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
demo.meeting(barrier);//1.在run方法传入实例
}
}).start();
}
}
}
输出:
先事true了,全被叫醒执行下面这段代码
没来的呢
也抛异常了。这就是broken的传递性。
--------------------
reset:
这个方法可以获取等待的数量
package com.roocon.thread.tb5;
import java.util.Random;
import java.util.concurrent.CyclicBarrier;
public class Demo {//Fdy123
Random random = new Random();
public void meeting(CyclicBarrier barrier) {
try {
Thread.sleep(random.nextInt(4000));
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 到达会议室,等待开会..");
if(Thread.currentThread().getName().equals("Thread-7")) {
//Thread.currentThread().interrupt();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
barrier.reset();
}
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Demo demo = new Demo();
CyclicBarrier barrier = new CyclicBarrier(10, new Runnable() {//0.new一个barrier
@Override
public void run() {
System.out.println("好!我们开始开会...");
}
});
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
demo.meeting(barrier);//1.在run方法传入实例
}
}).start();
}
// 监控等待线程数
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("等待的线程数 " + barrier.getNumberWaiting());
System.out.println("is broken " + barrier.isBroken());
}
}
}).start();
}
}
看下reset方法:
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // 所有的线程broken为true
nextGeneration(); // 叫醒所有的
} finally {
lock.unlock();
}
}
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
此时有现成一直在等待了。
reset执行完毕又有线程进来就一直等待。
等待的线程就是Thread7
------Semaphore-----
共享锁和公平(非公平)
-----------------------------------tb5-------------------------------------