CyclicBarrier 可以使多个线程达到同一状态
package com.sqh.TestLimiter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CyclicBarrier;
public class TestLimiter {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(10);
for (int i=0;i<10;i++){
new Thread(() -> {
try {
System.out.println("开始集结");
barrier.await();//等待10个线程同时开启
System.out.println("集结完毕");
} catch (Exception e) {
e.printStackTrace();
}
}).start();
}
}
}
执行结果:
开始集结
开始集结
开始集结
开始集结
开始集结
开始集结
开始集结
开始集结
开始集结
开始集结
集结完毕
集结完毕
集结完毕
集结完毕
集结完毕
集结完毕
集结完毕
集结完毕
集结完毕
集结完毕
它维护了一个count值
private int count;
await方法会阻塞直到所有线程都到达
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
每次执行await count都会减1
int index = --count;
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
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
}
// loop until tripped, broken, interrupted, or timed out
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();
}
}
使用Lock保证线程安全 使用自旋的方式让线程阻塞一段时间
可以用它写一个接口压力测试 让多个线程一起访问接口
【CountDownLatch】
下面的代码实现了一个让三个线程顺序执行的例子。
package com.sqh.TestLimiter;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest {
public static void main(String[] args) {
CountDownLatch countDownLatch1 = new CountDownLatch(1);
CountDownLatch countDownLatch2 = new CountDownLatch(1);
CountDownLatch countDownLatch3 = new CountDownLatch(1);
Thread thread1 = new Thread(new MyTask(countDownLatch1,null,"1"));
Thread thread2 = new Thread(new MyTask(countDownLatch2,countDownLatch1,"2"));
Thread thread3 = new Thread(new MyTask(countDownLatch3,countDownLatch2,"3"));
thread1.start();
thread2.start();
thread3.start();
}
}
class MyTask implements Runnable{
CountDownLatch countDownLatchOut;
CountDownLatch countDownLatch;
String threadName;
public MyTask(CountDownLatch countDownLatch,CountDownLatch countDownLatchOut,String threadName) {
this.countDownLatch = countDownLatch;
this.countDownLatchOut = countDownLatchOut;
this.threadName = threadName;
}
@Override
public void run() {
try {
if (null != countDownLatchOut ) {
countDownLatchOut.await();
}
System.out.println("do my task"+threadName);
countDownLatch.countDown();
}catch (Exception e){
e.printStackTrace();
}
}
}
CountDownLatch底层是基于AQS 实现的
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
它实际是基于
Sync(int count) {
setState(count);
}
上面是他的构造函数 那么他的CountDown方法是如何实现的呢
public void countDown() {
sync.releaseShared(1);
}
在Sync中
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
tryReleaseShared 是由子类实现的,在CountDownLatch 中实现如下 它就是AQS中的state 减 1 ,使用cas的方式原子的将它更新。
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;
}
}
在AQS中
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;
}
只有getState() == 0 返回1 的时候大于 0 acquireSharedInterruptibly 方法返回
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);
}
}
自适应的自选操作