目录

什么是CountDownLatch

使用CountDownLatch

方法

1. countDown()

2. await()

案例

什么是CyclicBarrier

使用CyclicBarrier

方法

1. await() 

案例

什么是Semaphore

使用Semaphore

方法

1. acquire() 

2. release() 

案例


什么是CountDownLatch

CountDownLatch 允许一个或多个线程等待一组操作在其他线程中完成。CountDownLatch 是一次性的,计数器的值只能设置一次,且一旦倒数到零,就不能被重置。

使用CountDownLatch

方法

1. countDown()
  • 作用:递减 CountDownLatch 中的计数器。

  • 使用场景:通常在线程完成其工作后调用此方法。每次调用 countDown() 方法,计数器的值就会减少一。

  • 特点

    • 如果计数器的值已经为零,则调用 countDown() 方法不会有任何效果。

    • 计数器的值只能递减,不能递增。

    • 一旦计数器的值递减到零,就不能被重置。

2. await()
  • 作用:使当前线程等待,直到 CountDownLatch 中的计数器递减到零。

  • 使用场景:通常在需要等待其他线程完成工作时使用。例如,主线程需要等待所有子线程执行完毕后再继续执行。

  • 特点

    • 如果计数器的值已经为零,则调用 await() 方法会立即返回,不会阻塞当前线程。

    • 如果计数器的值大于零,则调用 await() 方法的线程会被阻塞,直到计数器的值递减到零。

    • await() 方法可以被中断。如果当前线程在等待时被中断,则会抛出 InterruptedException 异常。

案例

public static void main(String[] args) throws InterruptedException {
    // 计数器
    CountDownLatch countDownLatch = new CountDownLatch(6);
    for (int i = 1; i <= 6; i++) {
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " Start");
            countDownLatch.countDown(); // 计数器-1
        }, String.valueOf(i)).start();
    }
    // 阻塞等待计数器归零
    countDownLatch.await();
    System.out.println(Thread.currentThread().getName() + " End");
}

本案例中,countDown() 方法用于递减计数器,而 await() 方法用于等待计数器递减到零。通过这种方式,主线程能够确保所有子线程都执行完毕后再继续执行。

什么是CyclicBarrier

CyclicBarrier允许一组线程相互等待,直到所有线程都到达一个公共屏障点(Barrier)。与 CountDownLatch 不同,CyclicBarrier 是可重用的,可以在计数器归零后重置,因此可以用于多个场景下的循环同步。

使用CyclicBarrier

方法

1. await() 
  • 作用:使当前线程在屏障点等待,直到所有线程都到达屏障点。

  • 异常

    • InterruptedException:如果当前线程在等待时被中断。在这种情况下,线程会退出等待状态,并抛出 InterruptedException

    • BrokenBarrierException:如果屏障被破坏(例如,其他线程在等待时被中断或超时)。在这种情况下,所有正在等待的线程都会抛出 BrokenBarrierException

案例

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        // CyclicBarrier(int parties, Runnable barrierAction)
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, () -> {
            System.out.println("7个线程执行完毕");
        });
        for (int i = 1; i <= 7; i++) {
            final int tempInt = i;
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "这是第" + tempInt + "个线程");
                try {
                    cyclicBarrier.await(); // 等待
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

本案例中,我们创建了一个 CyclicBarrier 对象,指定了参与者数量为 7,并设置了一个屏障动作,当所有线程都到达屏障点时,会打印 "7个线程执行完毕"。然后创建了 7 个线程,每个线程在执行完任务后都会调用 cyclicBarrier.await() 方法到达屏障点等待。当所有线程都到达屏障点时,屏障动作会被执行。

什么是Semaphore

Semaphore 用于控制同时访问某个特定资源的线程数量。Semaphore 通过维护一组许可证来实现对资源的访问控制,每个许可证代表对资源的一次访问权限。

使用Semaphore

方法

1. acquire() 
  • 作用:从 Semaphore 中获取一个许可证。如果没有可用的许可证,则阻塞当前线程,直到获取到一个许可证。

  • 特点

    • 如果当前有可用的许可证,则立即获取一个,并减少可用许可证的数量。

    • 如果没有可用的许可证,则当前线程会被阻塞,直到其他线程释放许可证。

  • 异常:如果当前线程在等待许可证时被中断,则抛出 InterruptedException

2. release() 
  • 作用:释放一个许可证,将其返回给 Semaphore。这会增加可用的许可证数量,可能会唤醒正在等待许可证的线程。

  • 特点

    • 释放许可证后,Semaphore 中的可用许可证数量会增加。

    • 如果有其他线程正在等待许可证,则可能会唤醒一个或多个等待的线程。

案例

public static void main(String[] args) {
        // 创建一个Semaphore,初始许可证数量为3
        Semaphore semaphore = new Semaphore(3);

        // 创建5个线程,模拟对资源的访问
        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    // 获取一个许可证
                    semaphore.acquire();
                    System.out.println("线程" + Thread.currentThread().getName() + "访问资源");
                    // 模拟资源访问时间
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 释放一个许可证
                    semaphore.release();
                }
            }, "Thread-" + i).start();
        }
    }

本案例中,Semaphore 被用于限制对某个资源的并发访问。首先创建了一个 Semaphore 对象,初始许可证数量为 3。然后创建了 5 个线程,每个线程在执行时都会尝试获取一个许可证。如果获取到许可证,则访问资源,并在访问完成后释放许可证。

Logo

2万人民币佣金等你来拿,中德社区发起者X.Lab,联合德国优秀企业对接开发项目,领取项目得佣金!!!

更多推荐