java.util.concurrent.CountDownLatch
CountDownLatch是一个多线程控制工具类。允许一个或多个线程等待其他线程完成一系列操作后再继续执行。
初始化
构造方法需要传入参数count,指定线程可以执行前CountDownLatch的countDown方法需要被调用的次数。
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
主要方法
await()
把当前线程置为等待状态,直到CountDownLatch计数减至0。
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
await(long timeout, TimeUnit unit)
把当前线程置为等待状态,直到CountDownLatch计数减至0或者达到指定时长。
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
countDown()
CountDownLatch计数减1,如果计数为0则释放所有等待线程。
public void countDown() {
sync.releaseShared(1);
}
getCount()
获取当前CountDownLatch的count数值。
public long getCount() {
return sync.getCount();
}
示例
public class CountDownLatchDemo {
private static final int COUNT = 50;
private static final int sleepSecond = 3;
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
CountDownLatch countDownLatch = new CountDownLatch(COUNT);
//countDown方法的执行次数一定要与countDownLatch的计数器数量一致,否则无法将计数器清空导致主线程无法继续执行
for (int i = 0; i < COUNT; ++i) {
int threadId = i;
executorService.execute(() -> {
try {
Thread.sleep(sleepSecond);
System.out.println("ThreadId:" + threadId);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
} finally {
countDownLatch.countDown();
}
});
}
//主线程只等1秒,超过之后继续执行主线程
countDownLatch.await(1, TimeUnit.SECONDS);
executorService.shutdown();
System.out.println("CountDownLatchDemo done.");
}
}
java.util.concurrent.CyclicBarrier
CyclicBarrier允许多个线程相互等待,直到所有线程都达到一个共同的栅栏点。而且CyclicBarrier可以重复使用。
初始化
CyclicBarrier默认的构造方法是CyclicBarrier(int parties),指定栅栏拦截的线程数量。
CyclicBarrier的另一个构造函数CyclicBarrier(int parties, Runnable barrierAction),用于线程到达屏障时,会优先执行barrierAction,以便处理更复杂的业务场景。
public CyclicBarrier(int parties) {
this(parties, null);
}
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}
主要方法
getParties()
返回CyclicBarrier设置的线程数
public int getParties() {
return parties;
}
await()
调用时表示当前线程已经到达栅栏点,当前线程设置为等待状态。直到所有线程都到达栅栏点,当前线程才会被唤醒。
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
await(long timeout, TimeUnit unit)
调用时表示当前线程已经到达栅栏点,当前线程设置为等待状态。直到所有线程都到达栅栏点,当前线程才会被唤醒。如果超出指定的等待时间,则抛出TimeoutException异常,如果该时间小于等于零,则此方法根本不会等待。
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
return dowait(true, unit.toNanos(timeout));
}
isBroken()
判断栅栏是否处于中断状态。
public boolean isBroken() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return generation.broken;
} finally {
lock.unlock();
}
}
reset()
将栅栏重置初始化。
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // break the current generation
nextGeneration(); // start a new generation
} finally {
lock.unlock();
}
}
getNumberWaiting()
返回当前在栅栏等待的参与线程数目。
public int getNumberWaiting() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return parties - count;
} finally {
lock.unlock();
}
}
示例
public class CyclicBarrierDemo {
private static final int COUNT = 50;
private static CyclicBarrier cyclicBarrier = new CyclicBarrier(10, () -> {
System.out.println("ready!");
});
public static void main(String[] args) throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < COUNT; ++i) {
int threadId = i;
executorService.execute(() -> {
try {
System.out.println("ThreadId:" + threadId);
cyclicBarrier.await();
System.out.println("go! " + threadId);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
} catch (BrokenBarrierException e) {
System.out.println(e.getMessage());
}
});
}
System.out.println("CyclicBarrierDemo done.");
executorService.shutdown();
}
}
java.util.concurrent.Semaphore
Semaphore是一个计数信号量。它负责管理一组许可证。每个acquire()方法都会阻塞当前线程,直到获得一个可用的许可证。每个release()方法都会释放当前线程,并归还Semaphore一个可用的许可证。
初始化
public Semaphore(int permits) {
sync = new NonfairSync(permits);
}
public Semaphore(int permits, boolean fair) {
sync = fair ? new FairSync(permits) : new NonfairSync(permits);
}
主要方法
acquire()
public void acquire() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
acquireUninterruptibly()
public void acquireUninterruptibly() {
sync.acquireShared(1);
}
void acquire(int permits)
public void acquire(int permits) throws InterruptedException {
if (permits < 0) throw new IllegalArgumentException();
sync.acquireSharedInterruptibly(permits);
}
release(int permits)
public void release(int permits) {
if (permits < 0) throw new IllegalArgumentException();
sync.releaseShared(permits);
}
示例
public class SemaphoreDemo {
private static final int COUNT=3;
private static final int sleepSecond = 3;
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
//配置只能发布3个运行许可证
Semaphore semaphore = new Semaphore(COUNT);
for(int i=0;i<COUNT;++i){
int threadId = i;
executorService.execute(()->{
try{
//配置只能发布3个运行许可证
semaphore.acquire(1);
System.out.println("ThreadId:" + threadId);
Thread.sleep(sleepSecond);
semaphore.release(1);
} catch (InterruptedException e) {
System.out.println(e.getMessage());
}
});
}
System.out.println("SemaphoreDemo done.");
executorService.shutdown();
}
}