详解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日

相关文章

  • Java Thread 类和Runnable 接口详解

    Java Thread 类和 Runnable 接口详解 概述 Java 中的线程是并发编程的核心内容,可以同时执行多个任务。Java 提供了两种线程的方式:继承Thread类和实现Runnable接口。 Thread 类 Thread类是Java中的一个顶级类,使用它可以快速地创建并发程序。Java 程序中的 main() 方法也是一个线程,使用Threa…

    Java 2023年5月19日
    00
  • Java MongoDB数据库连接方法梳理

    Java MongoDB数据库连接方法梳理 简介 MongoDB是一种开源、高性能、非关系型文档型数据库。由于其高效性和强大的原生查询语言,越来越多的企业和开发者开始选择MongoDB作为他们的首选数据库。本篇文章将介绍如何在Java应用程序中连接MongoDB数据库。 步骤 1. 安装MongoDB 在连接MongoDB之前,我们需要先安装MongoDB。…

    Java 2023年5月20日
    00
  • java 字符串分割的三种方法(总结)

    Java 字符串分割是一种将字符串拆分为多个子字符串的技术。它是一个常见的字符串操作,用于从文本数据中提取所需的信息。 下面是java字符串分割的三种方法及其详细讲解: 方法一:使用split()方法进行分割 Java中String类有一个split()方法,可以根据指定的分隔符将字符串拆分为多个子字符串,并将结果存储在一个数组中。 String str =…

    Java 2023年5月26日
    00
  • JAVA中SpringBoot启动流程分析

    以下是详细的Java中SpringBoot启动流程分析。 1. SpringBoot启动流程概述 SpringBoot是一种快速构建Spring应用的工具,其启动过程分为以下几个步骤: 首先,通过maven或gradle的构建工具编译项目代码,并将SpringBoot框架及相关依赖集成进项目中。 接着,在启动类中通过SpringApplication.run…

    Java 2023年5月15日
    00
  • 详细图解Java中字符串的初始化

    为了详细讲解“详细图解Java中字符串的初始化”的完整攻略,我会按照以下步骤进行: 1. 什么是字符串? 在Java中,字符串是一个对象,用来表示一组字符序列(包括字母、数字、符号等)。Java字符串使用Unicode字符编码,并且是不可变的对象,也就是说,它的值无法被更改。 2. 字符串的初始化方式 Java中有多种方式可以初始化字符串。下面介绍最常用的四…

    Java 2023年5月26日
    00
  • Java jwt使用公钥字符串验证解析token锁方法详解

    Java JWT使用公钥字符串验证解析token方法详解 JSON Web Token (JWT) 是一种用于 Web 应用程序处理身份验证的开放标准(RFC 7519),可在不同站点或服务器之间安全地传输声明,泛指声明某个实体(主体)具有某个权限。 本文将介绍如何使用公钥字符串来验证和解析 JWT 令牌,以此保证您的 Web 应用程序的身份验证机制的安全性…

    Java 2023年5月20日
    00
  • java实现图书馆管理系统

    Java实现图书馆管理系统攻略 1. 简介 本文将介绍如何用Java语言实现一个简单的图书馆管理系统。该系统可以进行图书的借阅、归还、查看图书信息等功能。 2. 开发环境 Java JDK 1.8 及以上版本 Eclipse IDE 3. 技术栈 Java语言 MySQL数据库 JDBC API 4. 数据库设计 该系统的数据库需要设计三个表:图书表、借阅表…

    Java 2023年5月23日
    00
  • tk.mybatis扩展通用接口使用详解

    tk.mybatis扩展通用接口使用详解 什么是tk.mybatis? tk.mybatis是MyBatis的一个扩展插件,它进一步简化了MyBatis的使用。tk.mybatis对MyBatis进行了增强,提供了一套通用的Mapper接口,可以让我们写更少的代码来完成CRUD操作。同时tk.mybatis提供了一些实用的功能,例如自动填充创建时间和更新时间…

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