1.CountDownLatch
介绍:countDownLatch相对于join()在线程间通信更灵活方法。coutnDownLatch内部AQS实现,AQS的state参数作为计数器个数,当前线程调用await()后进入AQS阻塞队列,每个线程结束后调用countdown(),state计数器-1.使直到countDown=0时AQS调用其doReleaseShared()方法释放线程。
结构:AQS<--Sync<--CountDownLatch
state表示countDownLatch初始化时的个数。
API: public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
count表示几个线程,
countDown每调用一次,state就-1
public void countDown() {
sync.releaseShared(1);
}
await()让当前线程阻塞,直到 state=0 或被interrupte打断后抛出线程打断异常。
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
2.CyclicBarrier
介绍:循环栅栏锁,功能类似于CountDownLatch但是可复用的,适用于分段任务有序执行。但可以循环往复使用,所有线程到达屏障点后才会冲破屏障,进行下一次屏障累计。
CyclicBarrier中使用了独占锁ReentrantLock,实际还是AQS。
结构:CyclicBarrier-->Generation
CyclicBarrier中parties记录线程个数,count也记录线程个数,但cb.await();每调用一次count-1,直到count=0,如果有屏障动作,执行CyclicBarrier(count,Runnable barrierAction) 的barrierAction,并且所有线程从condition的条件队列中释放,count=paties重置计数器。
lock 是ReentrantLock独占锁,
trip是Command条件队列
genertation中 Boolean broker=false参数,是否冲破屏障
3.Semaphore
介绍:Semaphore可以实现countDownLath和CyclicBarrier的功能,但不同是计数器是增加的,release()释放一个信号量,acquire()是获取信号量。
调用acqure(count) 如果当前permits-count<0,调用的线程阻塞,如果permits-count>0,相减后返回;realse(count)每次调用,都会AQS阻塞队列中返回count个线程获取信号量。
结构:Semaphore-->Sync-->AQS Sync-->FairSync/UnFairSync
具有公平和非公平两种策略,在acqurie()时,根据线程获取信号量的先后顺序。默认非公平,使用AQS的hashQueuedProcessor()方法实现公平与非公平。
使用:
new Semaphore(permits), new Semaphore(permits,true),
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
信号量释放
semaphore.relase();/release(permits);
public void release() {
sync.releaseShared(1);
}
网友评论