详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别

详解Java CountDownLatch和CyclicBarrier

在多线程编程中,我们常常会用到Java中的并发工具类CountDownLatchCyclicBarrier,它们都是用于线程同步的一种工具。本文将从内部实现和场景上的区别来详细讲解这两种工具类。

CountDownLatch

CountDownLatch在多线程中被用于等待一个或多个事件完成后再执行某种操作。它的工作原理是:一个计数器被初始化为某个数值,只要每个事件完成,计数器就会减1。当计数器的值为0时,代表所有事件已完成,此时等待线程可以继续执行。

下面是一个示例,展示了CountDownLatch的使用:

import java.util.concurrent.CountDownLatch;

public class Example {
    public static void main(String[] args) {
        final CountDownLatch latch = new CountDownLatch(2);

        new Thread(() -> {
            try {
                System.out.println("Thread 1 is running");
                Thread.sleep(1000);
                System.out.println("Thread 1 is done");
                latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        new Thread(() -> {
            try {
                System.out.println("Thread 2 is running");
                Thread.sleep(2000);
                System.out.println("Thread 2 is done");
                latch.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();

        try {
            System.out.println("Waiting for threads to finish");
            latch.await();
            System.out.println("All threads are done");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出结果如下:

Waiting for threads to finish
Thread 1 is running
Thread 2 is running
Thread 1 is done
Thread 2 is done
All threads are done

在此示例中,我们创建了一个CountDownLatch对象,并将其初始化为2。然后,我们创建了两个线程,让它们执行一些耗时的操作,最后等待线程会在调用await()方法时阻塞,直到两个线程将计数器减为0,然后输出"All threads are done"。

CyclicBarrier

CyclicBarrier也是用于线程同步的一种工具。它跟CountDownLatch最大的区别是:CountDownLatch的计数器在减到0之后就不能再用了,而CyclicBarrier的计数器在减到0之后可以被重置,因此它也被称为“可循环屏障”。

CyclicBarrier的工作原理是:创建一个CyclicBarrier对象时需要指定一个线程数和一个barrier action,当这个线程数的线程全部执行到barrier action之后,这些线程才会继续向下执行。

下面是一个示例,展示了CyclicBarrier的使用:

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

public class Example {
    public static void main(String[] args) {
        final int THREADS_NUM = 3;
        final CyclicBarrier barrier = new CyclicBarrier(THREADS_NUM, () -> {
            System.out.println("All threads are done");
        });

        for (int i = 0; i < THREADS_NUM; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + " is running");
                    Thread.sleep(1000);
                    System.out.println(Thread.currentThread().getName() + " is done");
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }, "Thread-" + i).start();
        }
    }
}

输出结果如下:

Thread-0 is running
Thread-1 is running
Thread-2 is running
Thread-2 is done
Thread-1 is done
Thread-0 is done
All threads are done

在此示例中,我们创建了一个CyclicBarrier对象,并将其初始化为3,同时创建三个线程。每个线程都会执行一些耗时的操作,并调用await()方法等待其他线程执行完毕。当三个线程都执行到barrier,即计数器减为0时,会执行barrier action,输出"All threads are done"。三个线程输出的顺序不一定是一致的。

区别

  • 内部实现

CountDownLatch采用了AQS队列,共享变量是一个int类型的计数器,每当一个线程完成它的工作后,计数器就会减1。当计数器的值变为0时,所有等待的线程都会被唤醒。而CyclicBarrier使用了ReentrantLock和Condition和AQS队列实现,还有一个parties表示初始化时需要等待的线程个数,这个值保持不变。

  • 应用场景

CountDownLatch通常用于等待异步任务的结果返回,将结果合并后再执行接下来的操作。例如多个线程处理一堆请求,等这些线程全部处理完毕以后再将处理结果进行合并。CyclicBarrier通常用于在多个线程执行过程中,等待其他线程同步完成后再继续执行后面的业务逻辑,例如多个线程写入数据,最后将数据合并在一起并输出。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • Spring Security中如何获取AuthenticationManager对象

    在Spring Security中,可以通过使用AuthenticationManager来处理用户验证。在一些自定义的场景中,可能需要手动获取AuthenticationManager对象来完成验证等操作。下面就是获取AuthenticationManager对象的两条示例攻略: 1. 通过注入获取AuthenticationManager对象 在Spri…

    Java 2023年6月3日
    00
  • Jackson的用法实例分析

    Jackson的用法实例分析 本文将介绍Jackson在Java中的用法实例,包括POM文件的配置、解析JSON字符串和生成JSON字符串。 POM文件配置 为了使用Jackson,需要在项目的POM文件中添加以下依赖项: <dependency> <groupId>com.fasterxml.jackson.core</gro…

    Java 2023年5月26日
    00
  • Spring中SmartLifecycle的用法解读

    我将为你详细讲解“Spring中SmartLifecycle的用法解读”。 什么是SmartLifecycle? Spring Framework提供了一种SmartLifecycle接口,可以让我们以编程方式在application context中进行初始化和关闭操作,并在这两个过程中有更精细的控制。 该接口具有一些主要的生命周期方法: isAutoSt…

    Java 2023年5月19日
    00
  • Spring注解方式无法扫描Service注解的解决

    当使用Spring注解方式配置应用程序时,有时可能会出现在扫描Service注解时无法识别的问题。出现这个问题的原因一般是因为缺少在Spring中定义Service注解扫描器的配置或者配置错误。解决此类问题需要进行以下设置: 添加@Service注解扫描器。 要使Spring扫描@Service注解,需要在Spring配置文件中配置注解扫描器,如下所示: &…

    Java 2023年5月20日
    00
  • Java用正则表达式实现${name}形式的字符串模板实例

    那么让我们来详细讲解一下“Java用正则表达式实现${name}形式的字符串模板实例”的完整攻略。 第一步:定义模板字符串 首先,我们需要定义一个模板字符串,例如: String template = "Hello, ${name}! Welcome to our website."; 这个模板字符串中包含了一个占位符${name},我们…

    Java 2023年5月29日
    00
  • java反射实现javabean转json实例代码

    Java反射实现JavaBean转JSON实例代码攻略 什么是Java反射? Java反射是指在运行时来操作Java对象的能力。通过Java反射,我们可以在运行期间分析类的内部信息,并调用类的方法、获取属性等。我们可以利用Java反射来实现一些动态编程的功能,如动态代理、依赖注入等。 如何使用Java反射实现JavaBean转JSON? JavaBean是J…

    Java 2023年5月26日
    00
  • SpringBoot整合WxJava开启消息推送的实现

    下面我将为您详细讲解“SpringBoot整合WxJava开启消息推送的实现”的完整攻略。 简介 WxJava 是微信开发 Java SDK的全称,是以易用性和高性能为设计目标的微信 Java开发工具包,支持公众号、小程序、企业微信和开放平台等微信平台的开发。本文将基于 SpringBoot 框架和 WxJava SDK,实现微信消息推送的功能。推送包括文本…

    Java 2023年5月23日
    00
  • 详解用Spring Boot零配置快速创建web项目

    使用Spring Boot可以快速创建Web项目,而且不需要进行繁琐的配置。下面是使用Spring Boot零配置创建Web项目的完整攻略: 创建一个Maven项目,并在pom.xml文件中添加以下依赖项: <dependency> <groupId>org.springframework.boot</groupId> &…

    Java 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部