掌握Guava的并发工具:轻松应对复杂并发场景

news2024/11/23 15:25:32

推荐语

这篇文章介绍了 Guava 的一些常用并发工具类的使用方法。通过学习这些工具类,我们可以轻松地处理异步操作。这些工具类不仅功能丰富,还大大简化并发编程的复杂性。无论你是初学者还是经验丰富的开发者,这篇文章都会对你在并发编程方面有所帮助。

关于Guava的并发工具

Guava提供了一些丰富的并发工具,帮助开发者更好地处理并发编程中的问题。例如,Guava提供了ListenableFuture、CountDownLatch、CyclicBarrier等工具。这些工具对Java并发包(java.util.concurrent)进行了扩展,使其功能更强大,使用更方便。

具体来说,其中ListenableFuture是Guava对Java Future的扩展,它允许你注册回调函数,当Future的计算结果可用时,这个回调函数会被执行。CountDownLatch和CyclicBarrier则是用于同步的工具类,它们可以让一组线程等待彼此,然后再一起执行。

Guava的并发工具盘点

Guava提供的并发工具当然不仅仅只有ListenableFuture、CountDownLatch、CyclicBarrier等,还有很多其他的,博主这里算是抛砖引玉吧,把我用过的,我认为比较好用的,在这里给大家梳理总结一下,如果大家用到了其他更好用的,欢迎在评论区告诉,一起深入交流。那么本篇文章的主角就是ListenableFuture、CountDownLatch和CyclicBarrier,那么下面先简单的盘一下这几个类的功能特性:

  • ListenableFuture:它是Guava对JDK的Future接口的扩展。相比于传统的Future,ListenableFuture允许你注册一个回调函数,一旦计算完成,这个回调函数就会被执行。这使得ListenableFuture在处理异步计算的结果时提供了更大的灵活性。
  • CountDownLatch:这是Java中的一个并发工具类,用于协调多个线程之间的同步。CountDownLatch能够使一个线程等待其他线程完成各自的工作后再执行。例如,你可以使用CountDownLatch来确保在继续执行主线程之前,一组工作线程已经完成了它们的初始化工作。
  • CyclicBarrier:这是Java中的一个同步工具类。CyclicBarrier可以让一组线程互相等待,直到所有线程都达到某个状态后再一起执行。这在并行计算中特别有用,例如,你可能想要在所有线程都完成了它们的一部分计算后,再进行一次汇总操作。CyclicBarrier可以确保所有线程都在同一时间点进行这个汇总操作。

环境配置

目前maven中央仓库的最新版本是32.1.3-jre,本篇文章的所有示例也是基于这个版本:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

Guava的并发工具如何使用

ListenableFuture

Guava类库的ListenableFuture是一个强大的工具,它扩展了Java的Future接口,增加了注册回调函数的功能。下面是一个使用Guava的ListenableFuture的示例:

public class ListenableFutureExample {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        ListeningExecutorService listeningExecutorService = MoreExecutors.listeningDecorator(executorService);
        ListenableFuture<String> future = listeningExecutorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                // 模拟异步任务
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + ":异步任务执行完毕");
                return "异步任务执行成功:success";
            }
        });
        Futures.addCallback(future, new FutureCallback<String>() {
            @Override
            public void onSuccess(String result) {
                // 异步任务执行成功后的回调方法
                System.out.println(Thread.currentThread().getName() + ":异步任务执行成功,结果是:" + result);
                listeningExecutorService.shutdown();//收到回调结果后,建议关注线程池,否则监听回调程序会一直阻塞,不会结束;
            }
            @Override
            public void onFailure(Throwable t) {
                // 异步任务执行失败后的回调方法
                System.out.println("异步任务执行失败");
                t.printStackTrace();
            }
        }, executorService);
        System.out.println(Thread.currentThread().getName() + ":主线程继续执行其他任务...");
    }
}

在上面这个示例中,我们使用了Guava的ListeningExecutorService来创建一个线程池,并通过submit方法提交了一个异步任务。该异步任务模拟了一个耗时操作,等待2秒后返回结果。然后,我们使用Futures.addCallback方法为ListenableFuture对象注册了一个回调函数。当异步任务执行成功时,会调用onSuccess方法,并打印出异步任务的结果;当异步任务执行失败时,会调用onFailure方法,并打印出异常信息。最后,主线程继续执行其他任务。需要注意的是:在这里我关闭了线程池,否则监听回调程序会一直阻塞,不会结束;

CountDownLatch

在下面这个示例中,我们使用了Guava类库的Uninterruptibles.awaitUninterruptibly()方法来等待CountDownLatch的计数器变为0。这与使用Java标准库中的latch.await()方法类似,但Guava提供的方法能够更优雅地处理中断。其余部分与之前的示例相同,创建了多个工作线程,并使用CountDownLatch来协调它们的执行。当所有工作线程都调用latch.countDown()方法后,计数器将变为0,然后主线程通过Uninterruptibles.awaitUninterruptibly(latch)等待所有工作线程执行完毕,并输出"All worker threads have finished."。


public class GuavaCountDownLatchExample {
    public static void main(String[] args) {
        int numberOfThreads = 3;
        CountDownLatch latch = new CountDownLatch(numberOfThreads);
        for (int i = 0; i < numberOfThreads; i++) {
            new Thread(new Worker(latch), "Thread" + i).start();
        }
        Uninterruptibles.awaitUninterruptibly(latch); // 使用Guava的Uninterruptibles类等待所有工作线程执行完毕
        System.out.println("All worker threads have finished.");
    }
}

class Worker implements Runnable {
    private final CountDownLatch latch;

    Worker(CountDownLatch latch) {
        this.latch = latch;
    }
    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " is working.");
            Thread.sleep((long) (Math.random() * 1000)); // 模拟工作线程执行的任务
            System.out.println(Thread.currentThread().getName() + " has finished.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            latch.countDown(); // 工作线程完成任务后,计数器减一
        }
    }
}

CyclicBarrier

在 Guava 类库中,没有直接提供 CyclicBarrier 类。CyclicBarrier 是 Java 标准库中的一个类,它可以用于多线程间的同步。这里也简单梳理一下他的用法,因为在做多线程间同步协调的相关业务时,CountDownLatch和CyclicBarrier,是两个绕不过去的选项,这里放在一起也好作个对比。

在下面这个示例中,创建了10个工作线程,每个线程都执行相同的任务。这些线程通过CyclicBarrier进行同步,确保所有线程都达到屏障点(即调用cyclicBarrier.await()方法)后再一起继续执行。当所有线程都调用cyclicBarrier.await()方法后,屏障会被打破,所有线程可以继续执行后续的任务。在这个示例中,后续的任务是输出线程名称和"is running"的消息。


public class CyclicBarrierExample {
    public static void main(String[] args) {
        final int totalThread = 10;
        CyclicBarrier cyclicBarrier = new CyclicBarrier(totalThread);

        for (int i = 0; i < totalThread; i++) {
            new Thread(new Task(cyclicBarrier), "Thread" + i).start();
        }
    }
}

class Task implements Runnable {
    private CyclicBarrier cyclicBarrier;

    public Task(CyclicBarrier cyclicBarrier) {
        this.cyclicBarrier = cyclicBarrier;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " is ready");
        try {
            cyclicBarrier.await(); //等待其他线程到达屏障点
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + " is running");
    }
}

写在最后

希望这篇文章能够为你提供有关 Guava 的 并发工具类的使用方法,让你在处理异步任务时能够更加得心应手。如果你觉得这篇文章对你有所帮助,不妨点个赞并分享给你的朋友。同时,欢迎关注我的公众号(凡夫编程)/博客(凡夫贬夫),获取更多关于技术知识和实用工具的分享。你的支持是我们创作的动力,也是我们分享更多优质内容的动力。谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1326614.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年中国数据智能管理峰会(DAMS上海站2023)-核心PPT资料下载

一、峰会简介 数据已经成为企业的核心竞争力&#xff01;谁掌控数据、更好的利用数据、实现资产化&#xff0c;谁就会真正率先进入大数据时代。 1、数据智能管理趋势和挑战 在峰会上&#xff0c;与会者讨论了数据智能管理的最新趋势和挑战。随着数据量的不断增加&#xff0c…

本地websocket服务端结合cpolar内网穿透实现公网访问

文章目录 1. Java 服务端demo环境2. 在pom文件引入第三包封装的netty框架maven坐标3. 创建服务端,以接口模式调用,方便外部调用4. 启动服务,出现以下信息表示启动成功,暴露端口默认99995. 创建隧道映射内网端口6. 查看状态->在线隧道,复制所创建隧道的公网地址加端口号7. 以…

华为OD机试 - 区间交集 - 深度优先搜索dfs算法(滥用)(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述备注用例1、输入2、输出3、说明 四、解题思路1、核心思路&#xff1a;2、具体步骤 五、Java算法源码再重新读一遍题目&#xff0c;看看能否优化一下~解题步骤也简化了很多。 六、效果展示1、输入2、输出3、说明 华为OD机试 2…

【小呆的力学笔记】弹塑性力学的初步认知二:应力分析(1)

文章目录 1.1 一点的应力状态1.2 一点主应力状态1.3 应力偏张量、球张量、应力不变量 1.1 一点的应力状态 物体在受到外力或者自身不均匀的温度场等作用时&#xff0c;在其内部会产生内力&#xff0c;物体的内力与方向和截面都有关系。假设有一个受到外力作用的变形体&#xf…

【Linux】Linux线程概念和线程控制

文章目录 一、Linux线程概念1.什么是线程2.线程的优缺点3.线程异常4.线程用途5.Linux进程VS线程 二、线程控制1.线程创建2.线程终止3.线程等待4.线程分离 一、Linux线程概念 1.什么是线程 线程是进程内的一个执行流。 我们知道&#xff0c;一个进程会有对应的PCB&#xff0c;…

【LeetCode刷题笔记(12-1)】【Python】【有效的字母异位词】【排序/字符统计】【简单】

文章目录 引言有效的字母异位词题目描述提示 解决方案1&#xff1a;【排序】解决方案2&#xff1a;【字符统计】结束语 有效的字母异位词 引言 编写通过所有测试案例的代码并不简单&#xff0c;通常需要深思熟虑和理性分析。虽然这些代码能够通过所有的测试案例&#xff0c;但…

职场必备!这个微信管理效率神器一定要知道

很多小伙伴在管理微信时&#xff0c;都会遇到效率不高的问题&#xff0c;尤其是一些有多个微信号的人&#xff0c;如何高效管理微信成为了一道难题。 今天就给大家分享一款能高效管理微信的工具&#xff0c;让大家既能节省时间又可以提高工作效率&#xff01; 通过微信管理系…

Vue3-23-组件-依赖注入的使用详解

什么是依赖注入 个人的理解 &#xff1a; 依赖注入&#xff0c;是在 一颗 组件树中&#xff0c;由 【前代组件】 给 【后代组件】 提供 属性值的 一种方式 &#xff1b;这种方式 突破了 【父子组件】之间通过 props 的方式传值的限制&#xff0c;只要是 【前代组件】提供的 依…

自动化测试工具-Selenium:WebDriver的API/方法使用全解

我们上一篇文章介绍了Selenium的三大组件&#xff0c;其中介绍了WebDriver是最重要的组件。在这里&#xff0c;我们将看到WebDriver常用的API/方法&#xff08;注&#xff1a;这里使用Python语言来进行演示&#xff09;。 1. WebDriver创建 打开VSCode&#xff0c;我们首先引…

数据结构与算法之美学习笔记:39 | 回溯算法:从电影《蝴蝶效应》中学习回溯算法的核心思想

目录 前言如何理解“回溯算法”&#xff1f;两个回溯算法的经典应用内容小结 前言 本节课程思维导图&#xff1a; 我们在前面深度优先搜索算法利用的是回溯算法思想。这个算法思想非常简单&#xff0c;但是应用却非常广泛。它除了用来指导像深度优先搜索这种经典的算法设计之外…

原生微信小程序中使用-阿里字体图标-详解

步骤一 1、打开阿里巴巴矢量图标库 网址&#xff1a;iconfont-阿里巴巴矢量图标库 2、搜索字体图标&#xff0c;鼠标悬浮点击添加入库 3、按如下步骤添加到自己的项目 步骤二 进入微信开发者工具 1、创建 fonts文件夹 > iconfont.wxss 文件&#xff0c;将刚才的代码复制…

GLTF/GLB模型在线预览、编辑、动画查看以及材质修改

在线工具推荐&#xff1a; 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 GLTF在线编辑器提供了一个内置的模型查看器&#xff0c;可以加载和预…

NC65凭证保存时,报“错误:凭证内部错误号:[10001]凭证借贷金额不平!”

NC65凭证保存时&#xff0c;报“错误:凭证内部错误号&#xff1a;[10001]凭证借贷金额不平&#xff01;” 实际就是分录少录了2分钱。加上去即可。 代码排查&#xff1a; nc.bs.gl.voucher.VoucherBO.save(VoucherVO voucher, Boolean isneedcheck) throws BusinessExceptio…

微服务之服务注册与发现

服务注册发现 服务注册就是维护一个登记簿&#xff0c;它管理系统内所有的服务地址。当新的服务启动后&#xff0c;它会向登记簿交待自己的地址信息。服务的依赖方直接向登记簿要 Service Provider 地址就行了。当下用于服务注册的工具非常多 ZooKeeper&#xff0c;Consul&…

Centos8一键启动多个Springboot jar包 改进版

一、前言 上篇《Centos8一键启动多个Springboot jar包》写了在centos环境下如何快速启动多个jar包。实际使用下来还是会发现不够完美&#xff0c;如我想重新启动10个jar包里面的两个&#xff0c;我得这么写&#xff1a; ./start.sh restart test1.jar; ./start.sh restart te…

为什么项目管理工具需要项目财务信息?

在讨论项目时&#xff0c;钱是绕不开的话题。 资金是项目管理中最重要的因素之一&#xff0c;与范围和时间并列&#xff0c;三者共同构成了 “三重约束”。例如&#xff0c;如果缩短项目时间&#xff0c;就必须增加成本。 如果无法清楚了解开支及其对项目的影响&#xff08;反…

TrustZone之可信操作系统

有许多可信内核&#xff0c;包括商业和开源的。一个例子是OP-TEE&#xff0c;最初由ST-Ericsson开发&#xff0c;但现在是由Linaro托管的开源项目。OP-TEE提供了一个功能齐全的可信执行环境&#xff0c;您可以在OP-TEE项目网站上找到详细的描述。 OP-TEE的结构如下图所示&…

成熟又专业的内外网文件交换系统,了解一下!

近年来全球网络安全威胁态势的加速严峻&#xff0c;使得企业对于网络安全有了前所未有的关注高度。越来越多的企业在网络安全体系建设和日常工作中&#xff0c;都面临一个核心问题&#xff0c;如何保护企业核心数据资产&#xff1f; 绝大多数企业都在内部实施了网络隔离&#x…

WEB测试之兼容性测试

1. 软件兼容性测试 兼容性测试是指待测试项目在特定的硬件平台上&#xff0c;不同的应用软件之间&#xff0c;不同的操作系统平台上&#xff0c;在不同的网络等环境中能正常的运行的测试。 兼容性测试的目的&#xff1a;待测试项目在不同的操作系统平台上正常运行&#xff0c…

如何通过ETLCloud的API对接功能实现各种SaaS平台数据对接

前言 当前使用SaaS系统的企业越来越多&#xff0c;当我们需要对SaaS系统中产生的数据进行分析和对接时就需要与SaaS系统提供的API进行对接&#xff0c;因为SaaS一般是不会提供数据库表给企业&#xff0c;这时就应该使用ETL&#xff08;Extract, Transform, Load&#xff09;的…