java.util.concurrent包之tools

257 阅读3分钟
原文链接: tedhacker.top

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();
    }
}