寒假打卡05_1月17日

Java 并发工具类——CountDownLatch、CyclicBarrier、Semaphore 等

在多线程编程中,Java 提供了一些实用的并发工具类来简化线程间的协调和同步工作。这些工具类包括 CountDownLatchCyclicBarrierSemaphore 等。它们可以帮助我们更高效地管理线程的执行顺序、协调线程间的任务分配以及控制并发线程的数量。

CountDownLatch

CountDownLatch 是一个同步辅助类,用于在一个或多个线程完成一组操作之前,使一个或多个线程一直等待。它允许一个或多个线程等待其他线程完成某些操作。

使用场景

  • 等待多个线程完成初始化工作后再继续执行主线程
  • 实现并行任务的管理,如并行计算

示例代码

下面是一个使用 CountDownLatch 的示例,展示了如何等待多个线程完成任务后再继续执行主线程:

import java.util.concurrent.CountDownLatch;

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        int threadCount = 3;
        CountDownLatch latch = new CountDownLatch(threadCount);

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

        System.out.println("Main thread is waiting for workers to finish...");
        latch.await();
        System.out.println("All workers have finished. Main thread is resuming...");
    }

    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() + " is working...");
                Thread.sleep(2000); // Simulate work
                System.out.println(Thread.currentThread().getName() + " has finished.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                latch.countDown();
            }
        }
    }
}

在上述代码中,主线程创建了三个工作线程,并等待它们完成任务后再继续执行。每个工作线程在完成任务后会调用 countDown() 方法减少计数器,当计数器归零时,主线程继续执行。

CyclicBarrier

CyclicBarrier 是一个同步辅助类,它允许一组线程互相等待,直到所有线程都到达一个公共的屏障点。与 CountDownLatch 不同的是,CyclicBarrier 在释放等待线程后可以重用。

使用场景

  • 实现多线程任务的分阶段执行
  • 多线程计算中,需要在某个阶段等待所有线程完成后再进行下一阶段

示例代码

下面是一个使用 CyclicBarrier 的示例,展示了如何在多个线程都到达屏障点后再继续执行:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
            System.out.println("All threads have reached the barrier. Continuing...");
        });

        for (int i = 0; i < threadCount; 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() + " is working...");
                Thread.sleep(2000); // Simulate work
                System.out.println(Thread.currentThread().getName() + " has reached the barrier.");
                barrier.await();
                System.out.println(Thread.currentThread().getName() + " is continuing...");
            } catch (InterruptedException | BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述代码中,三个工作线程在完成任务后调用 barrier.await() 等待,直到所有线程都到达屏障点后,再继续执行后续任务。

Semaphore

Semaphore 是一个计数信号量,用于控制同时访问特定资源的线程数量。它通过维护一个许可集来实现线程间的同步,线程在进入临界区时需要获取许可,离开时释放许可。

使用场景

  • 限制对某些资源的并发访问,如数据库连接池
  • 实现流量控制,防止资源过度消耗

示例代码

下面是一个使用 Semaphore 的示例,展示了如何限制同时访问资源的线程数量:

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
    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 {
                System.out.println(Thread.currentThread().getName() + " is waiting for permit...");
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName() + " has acquired permit and is working...");
                Thread.sleep(2000); // Simulate work
                System.out.println(Thread.currentThread().getName() + " has finished and is releasing permit.");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release();
            }
        }
    }
}

在上述代码中,主线程创建了五个工作线程,但由于信号量的许可数量为 2,最多只能有两个线程同时访问资源,其余线程需要等待许可。

总结

Java 并发工具类提供了一些非常有用的工具来简化线程间的协调和同步工作。CountDownLatchCyclicBarrierSemaphore 是其中最常用的工具类,它们分别用于实现线程的等待、分阶段执行和并发访问控制。通过合理使用这些工具类,我们可以编写出更加高效和健壮的多线程程序。

希望通过本篇文章,大家对 Java 并发工具类有了更深入的了解。在接下来的文章中,我们将继续探讨更多关于 Java 多线程的知识点,敬请期待!

posted @ 2025-01-17 09:08  aallofitisst  阅读(21)  评论(0)    收藏  举报