java并发体系--并发工具类

CyclicBarrier

CyclicBarrier是Java并发工具类之一,它允许一组线程互相等待,直到达到某个公共屏障点(barrier point)。

CyclicBarrier的主要特性包括:

  1. 构造函数:可以通过构造函数指定等待的线程数目。一旦线程数目达到指定值,所有等待的线程将被释放。

  2. await()方法:线程通过调用await()方法进入等待状态,直到所有线程都到达屏障点。

  3. 动作(Action):可以指定在屏障点达到之后,执行的额外动作。

代码示例:

java 复制代码
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {

    public static void main(String[] args) {
        final int numThreads = 3;
        final CyclicBarrier barrier = new CyclicBarrier(numThreads, new Runnable() {
            // 在所有线程到达屏障点之后,执行的额外动作
            @Override
            public void run() {
                System.out.println("所有线程已经到达屏障点,开始执行额外动作");
            }
        });

        for (int i = 0; i < numThreads; i++) {
            final int threadNum = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println("线程" + threadNum + "正在执行任务");
                        // 模拟任务执行耗时
                        Thread.sleep(1000);
                        System.out.println("线程" + threadNum + "已经到达屏障点");
                        // 线程到达屏障点,等待其他线程到达
                        barrier.await();
                        System.out.println("线程" + threadNum + "继续执行任务");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

以上代码中,我们创建了一个CyclicBarrier对象,并指定等待的线程数目为3。每个线程在执行任务之后,首先调用await()方法进入等待状态,直到所有线程都到达屏障点。当所有线程到达屏障点之后,CyclicBarrier将执行指定的额外动作(即Runnable对象中的run()方法)。

运行以上代码,输出如下:

线程0正在执行任务
线程1正在执行任务
线程2正在执行任务
线程0已经到达屏障点
线程1已经到达屏障点
线程2已经到达屏障点
所有线程已经到达屏障点,开始执行额外动作
线程0继续执行任务
线程2继续执行任务
线程1继续执行任务

从输出结果可以看出,当所有线程都到达屏障点后,CyclicBarrier执行了额外动作,并且所有线程继续执行任务。

CountDownLatch

CountDownLatch是Java并发编程中的一个工具类,可以让一个或多个线程等待其他线程完成后再继续执行。它的原理是通过一个计数器来实现的,该计数器被初始化为一个正整数,每当一个线程完成自己的任务时,计数器的值会减1,当计数器的值变为0时,等待的线程就会被唤醒,继续执行。

下面是一个使用CountDownLatch的简单示例代码:

java 复制代码
import java.util.concurrent.CountDownLatch;

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

        // 创建三个线程
        Thread thread1 = new Thread(new Worker(latch));
        Thread thread2 = new Thread(new Worker(latch));
        Thread thread3 = new Thread(new Worker(latch));

        // 启动线程
        thread1.start();
        thread2.start();
        thread3.start();

        try {
            // 等待所有线程完成任务
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 所有线程完成任务后继续执行
        System.out.println("All workers have finished their tasks.");
    }

    static class Worker implements Runnable {
        private final CountDownLatch latch;

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

        @Override
        public void run() {
            try {
                // 模拟线程执行任务的耗时
                Thread.sleep((long) (Math.random() * 1000));

                System.out.println("Worker " + Thread.currentThread().getId() + " has finished its task.");

                // 任务完成后计数器减1
                latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述示例中,我们创建了一个CountDownLatch实例,初始计数器的值为3。然后创建了三个Worker线程,它们会执行一段耗时的任务,并在任务完成后将计数器的值减1。主线程调用latch.await()方法来等待所有线程完成任务,当计数器的值变为0时,主线程被唤醒,继续执行后续的代码。

每个Worker线程的run()方法中,模拟了执行任务的耗时操作,并在任务完成后调用latch.countDown()方法将计数器的值减1。

运行示例代码,输出结果类似于:

Worker 10 has finished its task.
Worker 11 has finished its task.
Worker 12 has finished its task.
All workers have finished their tasks.

可以看到,三个Worker线程执行完任务后,主线程才继续执行,并输出了"All workers have finished their tasks."。

CyclicBarrier 与CountDownLatch区别

CyclicBarrier和CountDownLatch是Java并发包中的两个类,用于控制并发线程的执行顺序和协作。

CyclicBarrier: CyclicBarrier可以理解为循环栅栏,它可以使一组线程在某个点上等待,直到所有线程都到达这个点,然后所有线程继续执行下去。CyclicBarrier可以被重用,即当线程达到CyclicBarrier后,CyclicBarrier会重置计数,线程可以再次使用它。

CountDownLatch: CountDownLatch则是一种倒计数器,它允许一个或多个线程等待一组操作完成后再继续执行。CountDownLatch的计数器只能被减少,一旦计数器达到0,则等待的线程可以继续执行。

区别:

  1. 功能不同: CyclicBarrier主要用于等待所有线程到达某个点,然后再继续执行;而CountDownLatch主要用于等待一组线程执行完毕,然后再继续执行。

  2. 使用方式不同: CyclicBarrier通过调用await()方法进入等待状态,当所有线程都到达await()点时,才会继续执行。而CountDownLatch通过调用countDown()方法减少计数器的值,线程通过调用await()方法等待计数器值为0。

  3. 可重用性不同: CyclicBarrier可以被重复使用,一旦所有线程到达await()点,计数器会自动重置;而CountDownLatch只能被使用一次,一旦计数器值为0,就不能再次使用。

  4. 等待状态不同: CyclicBarrier可以在等待状态中响应中断,即当线程等待时,可以通过调用interrupt()方法中断线程;而CountDownLatch在等待状态中无法中断线程,只能等待计数器值为0后继续执行。

总结

CyclicBarrier和CountDownLatch都是Java并发编程中常用的同步工具,用于协调多个线程之间的执行顺序和并发操作。

  1. CyclicBarrier: CyclicBarrier是一个同步工具,用于等待一组线程达到某个共同的屏障点,然后再继续执行。它的作用是让一组线程在某个点上等待,直到所有线程都到达这个点后才能继续执行。常用于多线程计算中的数据分片和并行计算。

CyclicBarrier的主要特性和使用方法包括:

  • 创建一个CyclicBarrier对象时,可以指定参与线程的数量。
  • 每个线程调用await()方法之后会被阻塞,直到所有线程都调用了await()方法。
  • 一组线程中的最后一个调用await()方法的线程会触发一个屏障动作,所有被阻塞的线程将被释放。
  • CyclicBarrier可以重复使用,一旦所有线程被释放,它将被重置并可以再次使用。
  1. CountDownLatch: CountDownLatch是一个同步工具,用于等待一个或多个线程完成某个任务后再继续执行。它的作用是让某个线程等待其他线程执行完毕后再继续执行。常用于让某个线程等待其他线程的任务完成。

CountDownLatch的主要特性和使用方法包括:

  • 创建一个CountDownLatch对象时,需要指定计数器的数量,表示需要等待完成的线程数量。
  • 每个线程完成任务后,可以调用countDown()方法来减少计数器的值。
  • 等待线程可以调用await()方法来阻塞等待,直到计数器的值为0。
  • 一旦计数器的值为0,await()方法将返回,等待线程可以继续执行。
相关推荐
枫叶_v17 分钟前
【SpringBoot】20 同步调用、异步调用、异步回调
java·spring boot·后端
鸣弦artha24 分钟前
蓝桥杯——杨辉三角
java·算法·蓝桥杯·eclipse
未知陨落31 分钟前
数据结构——二叉搜索树
开发语言·数据结构·c++·二叉搜索树
大波V532 分钟前
设计模式-参考的雷丰阳老师直播课
java·开发语言·设计模式
计算机-秋大田38 分钟前
基于微信小程序的平安驾校预约平台的设计与实现(源码+LW++远程调试+代码讲解等)
java·spring boot·微信小程序·小程序·vue·课程设计
无敌最俊朗@1 小时前
unity3d————接口基础知识点
开发语言·c#
《源码好优多》1 小时前
基于Java Springboot旅游信息推荐系统
java·spring boot·旅游
岁月无声code1 小时前
Spring Boot 牛刀小试 org.springframework.boot:spring-boot-maven-plugin:找不到类错误
java·spring boot·github
不爱学习的YY酱1 小时前
【计网不挂科】计算机网络第二章< 物理层 >习题库(含答案)
java·数据库·计算机网络
一丝晨光1 小时前
gcc 1.c和g++ 1.c编译阶段有什么区别?如何知道g++编译默认会定义_GNU_SOURCE?
c语言·开发语言·c++·gnu·clang·gcc·g++