0

0

掌握 Java 并发性:CompletableFuture、Fork/Join 及其他

花韻仙語

花韻仙語

发布时间:2024-12-13 20:21:01

|

926人浏览过

|

来源于dev.to

转载

掌握 java 并发性:completablefuture、fork/join 及其他

作为一名拥有多年经验的 java 开发人员,我见证了该语言的巨大发展,尤其是在并发领域。新功能的引入彻底改变了我们处理多线程编程的方式,使构建能够充分利用现代硬件的高性能应用程序变得更加容易。

completablefuture 是 java 并发工具包中最重要的补充之一。它提供了一种强大的异步计算方法,使我们能够轻松链接操作、组合结果并处理错误。我发现它在我需要编排多个独立任务的场景中特别有用。

以下是如何使用 completablefuture 的实际示例:

completablefuture usernamefuture = completablefuture.supplyasync(() -> fetchusername());
completablefuture emailfuture = completablefuture.supplyasync(() -> fetchemail());

completablefuture userfuture = usernamefuture.thencombine(emailfuture, (username, email) -> {
    return new user(username, email);
});

userfuture.thenaccept(user -> system.out.println("user created: " + user));

在此代码中,我们异步获取用户名和电子邮件,然后组合结果来创建 user 对象。 completablefuture 的美妙之处在于它允许我们以清晰、可读的方式表达这种复杂的异步逻辑。

fork/join 框架是我们并发工具库中的另一个强大工具。它专为递归分而治之问题而设计,非常适合对大型数组进行排序或处理树状数据结构等任务。该框架使用工作窃取算法,允许空闲线程从繁忙线程中“窃取”任务,确保系统资源的有效利用。

立即学习Java免费学习笔记(深入)”;

这是使用 fork/join 框架对大型数组的元素求和的示例:

public class sumtask extends recursivetask {
    private final long[] array;
    private final int start;
    private final int end;
    private static final int threshold = 10000;

    public sumtask(long[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    @override
    protected long compute() {
        if (end - start <= threshold) {
            long sum = 0;
            for (int i = start; i < end; i++) {
                sum += array[i];
            }
            return sum;
        } else {
            int mid = (start + end) / 2;
            sumtask left = new sumtask(array, start, mid);
            sumtask right = new sumtask(array, mid, end);
            left.fork();
            long rightresult = right.compute();
            long leftresult = left.join();
            return leftresult + rightresult;
        }
    }
}

// usage
forkjoinpool pool = forkjoinpool.commonpool();
long[] array = new long[1000000];
// ... fill array with values
sumtask task = new sumtask(array, 0, array.length);
long sum = pool.invoke(task);

这个示例演示了我们如何使用 fork/join 框架来并行化计算密集型任务。该框架负责在可用线程之间分配工作,使我们能够专注于算法的逻辑。

并行流是构建在 fork/join 框架之上的更高级别的抽象。它们提供了一种简单的方法来并行化集合操作,从而可以轻松地利用多核处理器来执行数据处理任务。我发现并行流在处理大型数据集时特别有用,其中可以对每个元素独立执行操作。

这是使用并行流处理大量数字的示例:

list numbers = arrays.aslist(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
long sum = numbers.parallelstream()
                  .filter(n -> n % 2 == 0)
                  .maptolong(n -> n * n)
                  .sum();
system.out.println("sum of squares of even numbers: " + sum);

在此代码中,我们使用并行流来过滤偶数、对它们进行平方并对结果求和。 parallelstream() 方法自动使用 fork/join 池在多个线程之间分配工作。

stampedlock 是 java 并发实用程序的最新补充。它旨在在读取比写入频繁得多的情况下提供比 reentrantreadwritelock 更好的性能。 stampedlock 允许三种锁定模式:写入、读取和乐观读取。

以下是如何使用 stampedlock 的示例:

public class point {
    private double x, y;
    private final stampedlock sl = new stampedlock();

    void move(double deltax, double deltay) {
        long stamp = sl.writelock();
        try {
            x += deltax;
            y += deltay;
        } finally {
            sl.unlockwrite(stamp);
        }
    }

    double distancefromorigin() {
        long stamp = sl.tryoptimisticread();
        double currentx = x, currenty = y;
        if (!sl.validate(stamp)) {
            stamp = sl.readlock();
            try {
                currentx = x;
                currenty = y;
            } finally {
                sl.unlockread(stamp);
            }
        }
        return math.sqrt(currentx * currentx + currenty * currenty);
    }
}

在此示例中,move 方法使用写锁来确保更新坐标时的独占访问。 distancefromorigin 方法使用乐观读取,它实际上并不锁定状态。如果乐观读取失败(即,如果在读取期间发生写入),它将回退到常规读取锁定。

知识画家
知识画家

AI交互知识生成引擎,一句话生成知识视频、动画和应用

下载

java 9 中引入的 flow api 为标准库带来了响应式编程。它提供了用于实现反应流规范的接口,允许具有非阻塞背压的异步流处理。虽然 flow api 本身相当低级,但它可以作为更高级别反应式库的基础。

这是使用 flow api 的简单示例:

public class SimplePublisher implements Flow.Publisher {
    private final List data = Arrays.asList(1, 2, 3, 4, 5);

    @Override
    public void subscribe(Flow.Subscriber subscriber) {
        subscriber.onSubscribe(new Flow.Subscription() {
            private int index = 0;

            @Override
            public void request(long n) {
                for (int i = 0; i < n && index < data.size(); i++) {
                    subscriber.onNext(data.get(index++));
                }
                if (index >= data.size()) {
                    subscriber.onComplete();
                }
            }

            @Override
            public void cancel() {
                index = data.size();
            }
        });
    }
}

public class SimpleSubscriber implements Flow.Subscriber {
    private Flow.Subscription subscription;

    @Override
    public void onSubscribe(Flow.Subscription subscription) {
        this.subscription = subscription;
        subscription.request(1);
    }

    @Override
    public void onNext(Integer item) {
        System.out.println("Received: " + item);
        subscription.request(1);
    }

    @Override
    public void onError(Throwable throwable) {
        System.err.println("Error: " + throwable.getMessage());
    }

    @Override
    public void onComplete() {
        System.out.println("Complete");
    }
}

// Usage
SimplePublisher publisher = new SimplePublisher();
SimpleSubscriber subscriber = new SimpleSubscriber();
publisher.subscribe(subscriber);

此示例演示了使用 flow api 的简单发布者-订阅者交互。发布者发出一系列整数,订阅者一次处理一个整数。

这些并发特性显着提高了我编写高效、可扩展的 java 应用程序的能力。 completablefuture 使异步编程变得更加直观,使我能够清楚地表达复杂的工作流程。 fork/join 框架对于并行化递归算法非常有价值,而并行流则简化了批量数据处理。

stampedlock 已被证明在我需要对并发访问进行细粒度控制的场景中非常有用,尤其是在读取密集的情况下。虽然我没有直接使用 flow api,但很高兴看到响应式编程原理成为 java 标准库的一部分。

我在使用这些功能时学到的重要教训之一是为工作选择正确工具的重要性。虽然并行流很方便,但它们并不总是每个并发任务的最佳选择。有时,使用 completablefuture 或 fork/join 框架的更底层方法可以提供更好的性能和控制。

我还发现这些功能通常组合起来效果最佳。例如,我可能使用 completablefuture 来协调多个异步任务,每个异步任务在内部都使用并行流进行数据处理。或者,我可能会使用 stampedlock 来保护使用 flow api 构建的反应式应用程序中的共享状态。

需要注意的是,虽然这些功能使并发编程变得更容易,但它们并不能消除仔细设计和测试的需要。并发错误仍然可能发生,而且它们通常很微妙且难以重现。我始终确保在适当的时候使用 jcstress 等工具彻底测试我的并发代码。

总之,java 的并发增强为开发人员提供了一套强大的工具来构建高性能应用程序。通过利用 completablefuture、fork/join 框架、并行流、stampedlock 和 flow api,我们可以创建响应迅速、高效且可扩展的系统,充分利用现代多核处理器。随着 java 的不断发展,我很高兴看到该语言的未来版本中将引入哪些新的并发功能。


我们的创作

一定要看看我们的创作:

投资者中心 | 投资者中央西班牙语 | 投资者中德意志 | 智能生活 | 时代与回响 | 令人费解的谜团 | 印度教 | 精英开发 | js学校


我们在媒体上

科技考拉洞察 | 时代与回响世界 | 投资者中央媒体 | 令人费解的谜团 | 科学与时代媒介 | 现代印度教

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

539

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

21

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

28

2026.01.06

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1134

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

213

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1893

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

21

2026.01.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

523

2023.08.10

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

Sass 教程
Sass 教程

共14课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号