Java中的并发工具类:CountDownLatch、CyclicBarrier与Semaphore

代码魔法师 2020-11-08 ⋅ 15 阅读

在Java中,为了解决多线程并发执行的问题,提供了一些并发工具类,其中最常用的三个是CountDownLatchCyclicBarrierSemaphore。这些工具类为我们提供了方便且高效的并发编程解决方案。

CountDownLatch(倒计时门栓)

CountDownLatch是一种能够阻塞线程直到某个事件完成的同步辅助类。它需要一个初始计数值,每当一个线程完成了某个事件,计数值就会减1。当计数值变为0时,所有在CountDownLatch上阻塞的线程将被释放。

使用CountDownLatch的典型场景是:等待多个子线程完成,再进行主线程的工作。例如,你想要统计某个任务需要的所有时间,你可以创建一个CountDownLatch,然后在每个子线程的工作完成时调用countDown()方法,主线程在await()方法上等待,直到所有子线程完成。

以下是一个简单的示例代码:

CountDownLatch latch = new CountDownLatch(3);

for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        // 子线程的工作
        latch.countDown();
    }).start();
}

try {
    latch.await();
    // 所有子线程工作完成,进行主线程的工作
} catch (InterruptedException e) {
    e.printStackTrace();
}

CyclicBarrier(循环栅栏)

CyclicBarrier是一种同步辅助类,它允许一组线程互相等待,直到所有线程都达到某一状态,然后这一组线程才会继续执行。和CountDownLatch不同,CyclicBarrier的计数值是可以重置的,当计数值达到初始值时,所有等待的线程都会继续执行。

使用CyclicBarrier的典型场景是:将一个任务分成N个子任务,只有这N个子任务都完成时,才继续进行下一阶段的任务。工作线程可以在Barrier上等待,直到线程都达到Barrier时,线程可以向下运行。

以下是一个简单的示例代码:

CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    // 子线程都达到Barrier后,执行的方法
});

for (int i = 0; i < 3; i++) {
    new Thread(() -> {
        // 子线程的工作
        barrier.await();
    }).start();
}

Semaphore(信号量)

Semaphore是一种用来控制同时访问特定资源的线程数量的同步辅助类。它维护了一个许可证计数器,线程可以通过调用acquire()方法来获取许可证,用完后再调用release()方法归还许可证。

使用Semaphore的典型场景是:限制对某个资源的并发访问量。例如,你想要控制同时访问某个数据库的线程数量,你可以创建一个Semaphore并设置许可证数量为最大并发数,每个线程在访问数据库之前先调用acquire()方法获取许可证,访问完后再调用release()方法归还许可证。

以下是一个简单的示例代码:

Semaphore semaphore = new Semaphore(3);

for (int i = 0; i < 5; i++) {
    new Thread(() -> {
        try {
            semaphore.acquire();
            // 线程的工作
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }).start();
}

总结:通过CountDownLatchCyclicBarrierSemaphore这三种并发工具类,我们可以更加方便地实现多线程并发编程。CountDownLatch用于等待一组线程的完成,CyclicBarrier用于等待多个线程达到某一状态,Semaphore用于控制同时访问某个资源的线程数量。在实际应用中,我们根据具体的需求选择合适的并发工具类来解决问题,以提高程序的性能和效率。


全部评论: 0

    我有话说: