Semaphore CountDownLatch 和 CyclicBarrier
前言
java并发包下提供的三个并发工具类。Semaphore CountDownLatch 和 CyclicBarrier
一、CountDownLatch
CountDownLatch能够等待另外一些线程完成各自工作之后,再继续执行。
常用方法
void countDown(); count值减一
void await(); 等待count值降为0
boolean await(long timeout, TimeUnit unit); 等待count值降为0 或者超时
demo
private void test() throws Exception {
int cnt = 10;
CountDownLatch countDownLatch = new CountDownLatch(cnt);
for (int i = 0; i < cnt; i++) {
new Thread("T-" + i) {
@Override
public void run() {
try {
//do something
System.out.println(Thread.currentThread().getName() + "start");
Thread.sleep(ThreadLocalRandom.current().nextInt(5) * 1000);
System.out.println(Thread.currentThread().getName() + "end");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
}
} .start();
}
//等待count值降为0,也就是前面十个线程执行完再进行后面的操作
countDownLatch.await();
//countDownLatch.await(1, TimeUnit.MINUTES);
System.out.println("exit");
}
二、Semaphore
Semaphore通过控制一定数量的允许(permit)的方式,来达到限制通用资源访问的目的。比如限制并发数,限制同时最多有多少个线程在处理任务。
常用方法
acquire() 获取通行
release() 释放通行
availablePermits() 查看通行剩余次数
getQueueLength() 查看排队的长度
demo
private void test() throws Exception {
Semaphore semaphore = new Semaphore(2);
for (int i = 0; i < 10; i++) {
new Thread("T-" + i) {
@Override
public void run() {
try {
semaphore.acquire();
try {
System.out.println(Thread.currentThread().getName() + "start");
//do something
Thread.sleep(10000 + (ThreadLocalRandom.current().nextInt(5) * 1000));
System.out.println(Thread.currentThread().getName() + "end");
} finally {
semaphore.release();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} .start();
}
Thread.sleep(300);
System.out.println("availablePermits = " + semaphore.availablePermits());
System.out.println("queueLength = " + semaphore.getQueueLength());
}
三、CyclicBarrier
循环栅栏,凑齐第一批parties个线程后,一起执行,然后接着凑齐下一批凑齐
构造函数
CyclicBarrier(int parties)
CyclicBarrier(int parties, Runnable barrierAction) 最后一个进入 barrier 的线程会执行barrierAction
常用方法
await() 在所有参与者都已经在此 barrier 上调用 await 方法之前,将一直等待。
await(long timeout, TimeUnit unit) 在所有参与者都已经在此屏障上调用 await 方法之前,等待超时报错TimeoutException。
getNumberWaiting() 返回当前在屏障处等待的参与者数目。
getParties() 返回要求启动此 barrier 的参与者数目。
demo
private void test() throws Exception {
CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
for (int i = 0; i < 5; i++) {
new Thread("T-" + i) {
@Override
public void run() {
try {
//do something
System.out.println(Thread.currentThread().getName() + "await");
cyclicBarrier.await();
//cyclicBarrier.await(15, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName() + "start");
Thread.sleep(5000 + ThreadLocalRandom.current().nextInt(5) * 1000);
System.out.println(Thread.currentThread().getName() + "end");
} catch (Exception e) {
e.printStackTrace();
}
}
} .start();
}
Thread.sleep(300);
System.out.println("NumberWaiting = " + cyclicBarrier.getNumberWaiting());
System.out.println("Parties = " + cyclicBarrier.getParties());
}