详解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并行执行任务的几种方案小结

    Java并行执行任务的几种方案小结 在Java领域,多线程是一种非常常见的处理并发任务的方式。但是,多线程在并发处理能力以及代码设计方式上存在一些限制和挑战。近年来,随着Java语言的发展和并发编程框架的增多,人们有了许多新的方法来在Java中并行执行任务。本文将讲述Java并行执行任务的几种方案,以及在实际使用中的注意事项。 传统的多线程 在Java中使用…

    Java 2023年5月18日
    00
  • 手把手写Spring框架

    手把手写Spring框架攻略 如果想手写一个Spring框架,可以按照以下步骤: 1.了解Spring框架的设计原理 Spring框架的设计原理是基于反转控制(IoC)和面向切面编程(AOP)。反转控制是指通过配置文件或注解将对象的创建和依赖注入由应用程序翻转到容器来管理,而不是应用程序管理。面向切面编程则是指通过 AOP 技术,在不修改原有代码的情况下,在…

    Java 2023年5月19日
    00
  • Java线程重复执行以及操作共享变量的代码示例

    Java线程是一种轻量级进程,可以同时执行多个线程,实现并发操作。有时候我们需要让线程重复执行某个任务,并且需要注意操作共享变量的线程安全问题。下面就是以代码示例的形式,详细讲解“Java线程重复执行以及操作共享变量”的完整攻略。 线程重复执行 线程重复执行的方式有多种,其中最常见的方式是使用循环语句,如while循环、for循环等。下面以while循环和延…

    Java 2023年5月18日
    00
  • Java RSA加密解密实现方法分析【附BASE64 jar包下载】

    Java RSA加密解密实现方法分析 本文介绍了Java中RSA加密解密的实现方法。主要讲解了如何生成密钥对、如何进行加密解密、如何将密钥序列化和反序列化等操作。同时为了方便实际开发,我们也提供了BASE64 jar包下载链接。 生成密钥对 首先我们需要使用Java中的KeyPairGenerator类来生成RSA密钥对。代码如下: KeyPairGener…

    Java 2023年5月20日
    00
  • 浅谈一下Java中集合的迭代方式

    那我开始讲解“浅谈一下Java中集合的迭代方式”。首先介绍下迭代方式的概念,简单来说,迭代方式就是对集合进行重复操作的方式,它代表了一种遍历集合元素的能力。在Java中,主要有以下三种迭代方式: 1. foreach循环迭代 使用foreach循环迭代时,需要在循环头部声明一个与集合对象所存储元素类型相匹配的变量,然后在循环体中使用该变量进行操作: List…

    Java 2023年5月26日
    00
  • 记一次线程爆满导致服务器崩溃的问题排查及解决

    那么我们就来详细讲解一下如何排查和解决线程爆满导致服务器崩溃的问题。 问题描述 我们的公司网站最近出现了一个严重的问题,由于线程爆满导致服务器崩溃,影响了服务的正常运行。经过初步排查发现,该问题主要集中在某个页面请求过程中,而其他页面的请求则没有出现问题。但是由于该问题不易复现,因此需要更加深入地排查问题。 排查过程 监控系统 首先,我们需要在服务器上安装监…

    Java 2023年5月26日
    00
  • java读取文件字符集示例方法

    针对“java读取文件字符集示例方法”的完整攻略,我将提供以下过程和两个示例: 一、文件字符集的概念和了解 在学习如何读取文件字符集之前,先了解以下文件字符集的概念。文件字符集可以理解为一个字符集编码方式,它规定了计算机语言在计算机内表示字符或者数字时所采用的编码方式。在不同的操作系统或者软件中,对于字符集的选择会不同。如果我们读取了一个文件,但是文件中的字…

    Java 2023年5月19日
    00
  • Spring框架十一种常见异常的解决方法汇总

    下面我来详细讲解Spring框架常见异常的解决方法汇总。 1. NoSuchBeanDefinitionException异常的解决方法 NoSuchBeanDefinitionException异常表示Spring容器中没有找到对应的bean定义。出现这个异常的原因可能是配置文件名字错误、类名错误、xml文件没有配置等原因。 解决方法:- 检查配置文件名字…

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