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

在Java的多线程编程中,经常会遇到需要控制线程并发的情况。Semaphore、CountDownLatch、CyclicBarrier是Java中常用的三个并发工具类,本文将详细介绍它们的使用方法。


Semaphore

Semaphore是一种计数信号量,用于控制同时访问特定资源的线程数量。它通过协调各个线程,以保证合理的使用公共资源。

Semaphore有两种模式:公平模式和非公平模式。在公平模式下,线程获取许可的顺序与它们请求许可的顺序相同。在非公平模式下,线程获取许可的顺序是不确定的。

下面是一个Semaphore的示例:

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(2);
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName() + " acquire a permit.");
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        semaphore.release();
                        System.out.println(Thread.currentThread().getName() + " release a permit.");
                    }
                }
            });
            thread.start();
        }
    }
}

在上面的示例中,Semaphore的许可数量为2。一开始,有两个线程同时获取了许可,然后另外三个线程等待许可的释放。当有一个线程释放了许可之后,等待队列中的一个线程获取到了许可。


CountDownLatch

CountDownLatch是一种同步工具类,它可以让一个线程等待其他线程完成它们的工作之后再执行。

CountDownLatch通过一个计数器来实现。计数器的初始值为线程的数量。当一个线程完成了它的工作之后,计数器的值就会减1。当计数器的值为0时,表示所有线程都已经完成了工作,等待的线程可以继续执行。

下面是一个CountDownLatch的示例:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " has finished.");
                    countDownLatch.countDown();
                }
            });
            thread.start();
        }
        countDownLatch.await();
        System.out.println("All threads have finished.");
    }
}

在上面的示例中,有5个线程执行相同的任务。当一个线程完成它的工作之后,计数器的值就会减1。当所有线程都完成了工作,主线程才会继续执行。


CyclicBarrier

CyclicBarrier是一种同步工具类,它可以让一组线程在到达一个屏障之前相互等待。当所有线程都到达屏障时,屏障才会打开,所有线程才能继续执行。

CyclicBarrier和CountDownLatch的区别在于:CountDownLatch是一次性的,计数器的值减到0之后就不能再次使用了;而CyclicBarrier可以循环使用,所有线程都到达屏障之后,计数器会重置,可以继续使用。

下面是一个CyclicBarrier的示例:

import java.util.concurrent.CyclicBarrier;

class CyclicBarrierExample {
    public static void main(String[] args) {
        final int parties = 3;
        final CyclicBarrier cyclicBarrier = new CyclicBarrier(parties, new Runnable() {
            @Override
            public void run() {
                System.out.println("All parties have arrived at the barrier.");
            }
        });
        for (int i = 0; i < parties; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                        System.out.println(Thread.currentThread().getName() + " has arrived at the barrier.");
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();
        }
    }
}

在上面的示例中,有3个线程执行相同的任务。当一个线程到达屏障之后,就会调用await()方法等待其他线程到达屏障。当所有线程都到达屏障之后,屏障才会打开,所有线程才能继续执行。

猿教程
请先登录后发表评论
  • 最新评论
  • 总共0条评论