- CountDownLatch
定义一个计数器,每个线程调用一次countDown时减一,直到变成零,await才会向下执行
@Test
public void test01() throws InterruptedException {
CountDownLatch countDownLatch=new CountDownLatch(2);
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(1);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
System.out.println(2);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}
}).start();
countDownLatch.await();
System.out.println("3");
}
上面主线程执行await方法将会阻塞,启动的一个线程执行了两次countDown方法,主线程才会向下执行。
源码解析
public void countDown() {
sync.releaseShared(1);
}
countDown执行时,释放同步标志位减1,
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
await执行时,内部类重写了AbstractQueuedSynchronizer的tryAcquireShared方法,
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
如果同步状态标志位为0,则表示获取成功。
CyclicBarrier
作用:让一组线程阻塞,直到所有的线程都到达屏障。
public class CyclicBarrierTest {
private static CyclicBarrier c = new CyclicBarrier(2, new A());
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
try {
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(1);
}
}).start();
try {
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(2);
}
private static class A implements Runnable {
@Override
public void run() {
System.out.println(3);
}
}
}
执行结果
初始化的时候定义了屏障的个数,和所有线程到达屏障的时候优先执行的线程。
CyclicBarrier使用案例:
处理一个Excel中的多个Sheet数据,每一个线程处理一个Sheet,最终由一个线程做汇总计算。
public class BankWaterService implements Runnable {
/**
* 创建四个屏障,处理完成后执行当前类的run方法
*/
private CyclicBarrier c = new CyclicBarrier(4, this);
/**
* 创建固定大小为4的线程池
*/
private Executor executor = Executors.newFixedThreadPool(4);
/**
* 结果集
*/
private ConcurrentHashMap<String, Integer> sheetBankWaterCount = new ConcurrentHashMap<String, Integer>();
private void count() {
for (int i = 0; i < 4; i++) {
// 每一个工作空间交给一个线程去执行
this.executor.execute(new Runnable() {
@Override
public void run() {
sheetBankWaterCount
.put(Thread.currentThread().getName(), 1);
try {
// 当前线程执行完成,阻塞到屏障
c.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
}
}
@Override
public void run() {
// 各个线程执行完任务,交个当前类的run来做汇总处理
int result = 0;
for (Entry<String, Integer> sheet : this.sheetBankWaterCount.entrySet()) {
result += sheet.getValue();
}
this.sheetBankWaterCount.put("result", result);
System.out.println(this.sheetBankWaterCount);
}
public static void main(String[] args) {
BankWaterService bankWaterService = new BankWaterService();
bankWaterService.count();
}
}
Semaphore限制线程的执行个数
案例:
public class SemaphoreTest {
private static final int THREAD_COUNT = 30;
private static ExecutorService threadPool = Executors
.newFixedThreadPool(THREAD_COUNT);
private static Semaphore s = new Semaphore(10);
public static void main(String[] args) {
for (int i = 0; i < THREAD_COUNT; i++) {
threadPool.execute(new Runnable() {
@Override
public void run() {
try {
// 限制只能有10个线程执行入访问数据操作
s.acquire();
System.out.println("save data");
s.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
threadPool.shutdown();
}
}
摘自《Java并发编程的艺术》