MST

星途 面试题库

面试题:Java中Barrier的常见类型及应用场景简述

请简要描述Java中常见的Barrier类型,比如CountDownLatch、CyclicBarrier等,并说明它们各自适用于哪些应用场景,同时给出简单的代码示例。
10.3万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

CountDownLatch

  1. 描述:CountDownLatch是一个同步辅助类,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成。它通过一个计数器来实现,该计数器初始化为一个正整数,表示需要等待的操作数。每当一个操作完成时,计数器减1,当计数器减到0时,所有等待的线程将被释放。
  2. 适用场景:适用于需要等待一组操作全部完成后,再继续执行后续操作的场景。例如,在多线程计算任务中,等待所有子任务计算完成后,汇总结果。
  3. 代码示例
import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    public static void main(String[] args) {
        int taskCount = 3;
        CountDownLatch latch = new CountDownLatch(taskCount);

        for (int i = 0; i < taskCount; i++) {
            new Thread(new Worker(latch)).start();
        }

        try {
            latch.await();
            System.out.println("所有任务已完成,主线程继续执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static class Worker implements Runnable {
        private final CountDownLatch latch;

        Worker(CountDownLatch latch) {
            this.latch = latch;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + " 开始执行任务");
                // 模拟任务执行
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + " 任务完成");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        }
    }
}

CyclicBarrier

  1. 描述:CyclicBarrier也是一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点(barrier point)。与CountDownLatch不同的是,CyclicBarrier的计数器可以重置,即可以重复使用。当所有线程到达屏障点时,屏障打开,所有线程可以继续执行,之后计数器重置,可以再次使用。
  2. 适用场景:适用于需要多线程之间相互等待,并且这种等待可以循环进行的场景。例如,在多线程迭代计算中,每一轮计算都需要等待所有线程完成当前轮次后,再开始下一轮。
  3. 代码示例
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    public static void main(String[] args) {
        int parties = 3;
        CyclicBarrier barrier = new CyclicBarrier(parties, () -> {
            System.out.println("所有线程已到达屏障点,开始下一轮");
        });

        for (int i = 0; i < parties; i++) {
            new Thread(new Worker(barrier)).start();
        }
    }

    static class Worker implements Runnable {
        private final CyclicBarrier barrier;

        Worker(CyclicBarrier barrier) {
            this.barrier = barrier;
        }

        @Override
        public void run() {
            try {
                System.out.println(Thread.currentThread().getName() + " 开始执行任务");
                // 模拟任务执行
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + " 等待其他线程到达屏障点");
                barrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Semaphore

  1. 描述:Semaphore是一个计数信号量,它维护了一组许可证(permit)。线程可以通过acquire()方法获取许可证,如果没有可用许可证,线程将被阻塞,直到有许可证可用。线程使用完许可证后,通过release()方法释放许可证。
  2. 适用场景:适用于控制对共享资源的并发访问数量。例如,数据库连接池,限制同时连接数据库的线程数量。
  3. 代码示例
import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    public static void main(String[] args) {
        int permits = 2;
        Semaphore semaphore = new Semaphore(permits);

        for (int i = 0; i < 5; i++) {
            new Thread(new Worker(semaphore)).start();
        }
    }

    static class Worker implements Runnable {
        private final Semaphore semaphore;

        Worker(Semaphore semaphore) {
            this.semaphore = semaphore;
        }

        @Override
        public void run() {
            try {
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName() + " 获取到许可证,开始执行任务");
                // 模拟任务执行
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName() + " 任务完成,释放许可证");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release();
            }
        }
    }
}