返回

多线程并发的世界里,如何优雅的协调工作

后端

CountDownLatch:减少计数

概述

CountDownLatch是一个同步工具,它允许一个或多个线程等待其他线程完成工作。它有一个计数器,当计数器减到0时,所有等待的线程都会被唤醒。

使用场景

CountDownLatch通常用于以下场景:

  • 主线程等待所有子线程完成任务后继续执行。
  • 一个线程等待多个线程完成任务后继续执行。
  • 多个线程等待一个共享资源可用后继续执行。

示例

以下是一个使用CountDownLatch的示例:

public class CountDownLatchDemo {

    public static void main(String[] args) {
        // 创建一个CountDownLatch,计数器为3
        CountDownLatch latch = new CountDownLatch(3);

        // 创建3个线程,每个线程都调用countDown()方法来减少计数器
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                System.out.println("子线程" + Thread.currentThread().getName() + "开始执行");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                latch.countDown();
                System.out.println("子线程" + Thread.currentThread().getName() + "执行结束");
            }).start();
        }

        // 主线程等待CountDownLatch的计数器减到0
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 所有子线程执行结束,主线程继续执行
        System.out.println("主线程执行结束");
    }
}

输出结果:

子线程Thread-0开始执行
子线程Thread-1开始执行
子线程Thread-2开始执行
子线程Thread-0执行结束
子线程Thread-1执行结束
子线程Thread-2执行结束
主线程执行结束

CyclicBarrier:循环屏障

概述

CyclicBarrier是一个同步工具,它允许一组线程等待直到所有线程都到达一个公共屏障点。当所有线程都到达屏障点时,屏障将被解除,所有线程将继续执行。

使用场景

CyclicBarrier通常用于以下场景:

  • 多个线程需要在同一时间执行某个任务。
  • 多个线程需要在完成某个任务后继续执行。

示例

以下是一个使用CyclicBarrier的示例:

public class CyclicBarrierDemo {

    public static void main(String[] args) {
        // 创建一个CyclicBarrier,屏障点为3
        CyclicBarrier barrier = new CyclicBarrier(3);

        // 创建3个线程,每个线程都调用await()方法来等待其他线程到达屏障点
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                System.out.println("子线程" + Thread.currentThread().getName() + "开始执行");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
                System.out.println("子线程" + Thread.currentThread().getName() + "执行结束");
            }).start();
        }

        // 所有子线程到达屏障点,屏障解除,所有线程继续执行
        System.out.println("主线程执行结束");
    }
}

输出结果:

子线程Thread-0开始执行
子线程Thread-1开始执行
子线程Thread-2开始执行
子线程Thread-0执行结束
子线程Thread-1执行结束
子线程Thread-2执行结束
主线程执行结束

Semaphore:信号量

概述

Semaphore是一个同步工具,它允许多个线程并发访问共享资源,但对访问共享资源的线程数量进行限制。

使用场景

Semaphore通常用于以下场景:

  • 控制对共享资源的访问。
  • 限制同时访问共享资源的线程数量。

示例

以下是一个使用Semaphore的示例:

public class SemaphoreDemo {

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

        // 创建10个线程,每个线程都尝试获取许可证来访问共享资源
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    // 获取许可证
                    semaphore.acquire();
                    System.out.println("子线程" + Thread.currentThread().getName() + "获取许可证,开始访问共享资源");
                    Thread.sleep(1000);
                    // 释放许可证
                    semaphore.release();
                    System.out.println("子线程" + Thread.currentThread().getName() + "释放许可证,结束访问共享资源");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        // 主线程等待所有子线程执行结束
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 所有子线程执行结束,主线程继续执行
        System.out.println("主线程执行结束");
    }
}

输出结果:

子线程Thread-0获取许可证,开始访问共享资源
子线程Thread-1获取许可证,开始访问共享资源
子线程Thread-2获取许可证,开始访问共享资源
子线程Thread-0释放许可证,结束访问共享资源
子线程Thread-3获取许可证,开始访问共享资源
子线程Thread-1释放许可证,结束访问共享资源
子线程Thread-4获取许可证,开始访问共享资源
子线程Thread-2释放许可证,结束访问共享资源
子线程Thread-5获取许可证,开始访问共享资源
子线程Thread-3释放许可证,结束访问共享资源
子线程Thread-6获取许可证,开始访问共享资源
子线程Thread-4释放许可证,结束访问共享资源
子线程Thread-7获取许可证,开始访问共享资源
子线程Thread-5释放许可证,结束访问共享资源
子线程Thread-8获取许可证,开始访问共享资源
子线程Thread-6释放许可证,结束访问共享资源
子线程Thread-9获取许可证,开始访问共享资源
子线程Thread-7释放许可证,结束访问共享资源
子线程Thread-8释放许可证,结束访问共享资源
子线程Thread-9释放许可证,结束访问共享资源
主线程执行结束