【并发编程篇】详解Forkjoin

这篇具有很好参考价值的文章主要介绍了【并发编程篇】详解Forkjoin。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【并发编程篇】详解Forkjoin,并发编程,python,java,开发语言

🍔什么是Forkjoin

Fork/Join 是一种在多线程领域中常用的算法或技术,它的核心思想是将大任务分割成若干个小任务,然后将这些小任务分配给多个线程并行处理,最终将结果合并起来。这种思想可以应用于多种场景,例如图像处理、批处理、并行排序等。

在 Java 中,Fork/Join 这种思想被封装在了 java.util.concurrent 包中的 ForkJoinPool 类和 RecursiveTask 类中。ForkJoinPool 类是一个线程池,用于管理多个线程的执行,而 RecursiveTask 类则是一个抽象类,用于定义可分解的任务。通过使用这些类,开发者可以非常方便地实现 Fork/Join 的并行计算功能,从而提高应用程序的性能和效率。

总之,Fork/Join 并不是一个框架,而是一种并发编程技术,它可以帮助开发者实现高效的并行计算,并发挥多核 CPU 的计算能力。

🎈Forkjoin的方法

Fork/Join 框架提供了一些核心的方法来支持任务的分解和合并,下面我会对这些方法进行理论讲解:

  • fork() 方法:fork() 方法用于将当前任务进行分解,将其拆分成更小的子任务并提交给 Fork/Join 框架进行并行处理。该方法会异步地启动一个新的子任务,并立即返回,不会阻塞当前线程。
  • join() 方法:join() 方法用于等待子任务的执行完成,并获取其结果。在调用 join() 方法之前,程序会阻塞当前线程,直到子任务的执行完成。如果子任务还没有完成,则当前线程会暂停执行,转而执行其他可执行任务,从而实现工作窃取的效果。
  • invoke() 方法:invoke() 方法用于提交一个任务给 Fork/Join 框架进行处理,并返回任务的执行结果。该方法会同步地启动一个任务,并阻塞当前线程,直到任务执行完成并返回结果。这个方法通常用于提交根任务或最顶层的任务。
  • RecursiveTask 类和 RecursiveAction 类:Fork/Join 框架提供了两个抽象类 RecursiveTask 和 RecursiveAction,用于定义可分解的任务。RecursiveTask 适用于需要返回结果的任务,而 RecursiveAction 适用于不需要返回结果的任务。这两个类都有一个抽象方法 compute(),我们需要在子类中实现该方法来定义具体的任务逻辑。
  • Work-Stealing(工作窃取):Fork/Join 框架采用了工作窃取算法,使得线程在处理完自己的任务后可以从其他线程的队列中偷取任务来执行。这种方式可以提高并行计算的效率和负载均衡性能。工作窃取是通过双端队列实现的,每个线程都有自己的任务队列,当一个线程完成自己队列中的任务后,它会尝试从其他线程的队列末尾窃取任务来执行。

这些方法和概念是 Fork/Join 框架中非常重要的部分,它们通过任务的分解、合并和工作窃取机制,实现了高效的并行计算。理解并熟练使用这些方法可以帮助开发者更好地利用 Fork/Join 框架来处理并行计算任务。

🎆代码实现

ForkjoinDemo.java

package org.Test6;

import java.util.concurrent.RecursiveTask;

public class ForkjoinDemo extends RecursiveTask<Long> {
    private Long start; // 1
    private Long end; // 1990900000
    // 临界值
    private Long temp = 10000L;

    public ForkjoinDemo(Long start, Long end) {
        this.start = start;
        this.end = end;
    }

    // 计算方法
    @Override
    protected Long compute() {
        if ((end - start) < temp) {
            Long sum = 0L;
            for (Long i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else { // forkjoin 递归
            long middle = (start + end) / 2; // 中间值
            ForkjoinDemo task1 = new ForkjoinDemo(start, middle);
            task1.fork(); // 拆分任务,把任务压入线程队列
            ForkjoinDemo task2 = new ForkjoinDemo(middle + 1, end);
            task2.fork(); // 拆分任务,把任务压入线程队列
            return task1.join() + task2.join();
        }
    }
}

Test.java

package org.Test6;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream;

public class Test {

    public static void test1() {
        Long sum = 0L;
        long start = System.currentTimeMillis();
        for (Long i = 1L; i <= 10_0000_0000; i++) {
            sum += i;
        }
        long end = System.currentTimeMillis();
        System.out.println("sum=" + sum + " 时间:" + (end - start));
    }

    // 会使用ForkJoin
    public static void test2() throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkjoinDemo(0L, 10_0000_0000L);
        ForkJoinTask<Long> submit = forkJoinPool.submit(task);// 提交任务
        Long sum = submit.get();
        long end = System.currentTimeMillis();
        System.out.println("sum=" + sum + " 时间:" + (end - start));
    }

    public static void test3() {
        long start = System.currentTimeMillis();
        // Stream并行流
        long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);
        long end = System.currentTimeMillis();

        System.out.println("sum=" + sum + " 时间:" + (end - start));
    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        test1();
        test2();
        test3();
    }

}

【并发编程篇】详解Forkjoin,并发编程,python,java,开发语言

在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!

【并发编程篇】详解Forkjoin,并发编程,python,java,开发语言文章来源地址https://www.toymoban.com/news/detail-795993.html

到了这里,关于【并发编程篇】详解Forkjoin的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • java并发编程:ArrayBlockingQueue详解

    ArrayBlockingQueue 顾名思义:基于数组的阻塞队列。数组是要指定长度的,所以使用 ArrayBlockingQueue 时必须指定长度,也就是它是一个有界队列。它实现了 BlockingQueue 接口,有着队列、集合以及阻塞队列的所有方法。 ArrayBlockingQueue 是线程安全的,内部使用 ReentrantLock 来保证。A

    2024年02月08日
    浏览(59)
  • java并发编程:LinkedBlockingQueue详解

    在集合框架里,想必大家都用过ArrayList和LinkedList,也经常在面试中问到他们之间的区别。ArrayList和ArrayBlockingQueue一样,内部基于数组来存放元素,而LinkedBlockingQueue则和LinkedList一样,内部基于链表来存放元素。 LinkedBlockingQueue实现了BlockingQueue接口,这里放一张类的继承关系图

    2024年02月08日
    浏览(62)
  • Java并发编程详解:实现高效并发应用的关键技术

    在当前的计算机领域,高效的并发编程对于Java开发人员而言变得越发重要。作为流行的编程语言,Java提供了强大的并发编程支持,使开发人员能够充分发挥多核处理器和线程的潜力,构建高性能、高吞吐量的应用程序。本文将深入探讨Java并发编程的关键技术,包括线程安全

    2024年02月13日
    浏览(50)
  • Java并发编程之线程池详解

    目录 🐳今日良言:不悲伤 不彷徨 有风听风 有雨看雨 🐇一、简介 🐇二、相关代码 🐼1.线程池代码 🐼2.自定义实现线程池 🐇三、ThreadPoolExecutor类 首先来介绍一下什么是线程池,线程池是一种利用池化技术思想来实现的线程管理技术,主要是为了复用线程、便利地管理线程

    2024年02月12日
    浏览(43)
  • 【java】开发——《并发编程》

    目录 一.jmm 二.并发了什么 1.只有一个核(单核)并发还有没有意义 2.单核,还有什么可见性问题 3.并发和并行 三.volitaile 1.变量的可见性问题 2.原因是什么 3.本次修改的变量直接刷到主内存 4.声明其他内存对于这个地址的缓存无效 四.happens-befo 1.顺序性问题 五.volitaile+cas 1.原

    2024年02月22日
    浏览(48)
  • 【Java 并发编程】一文详解 Java 内置锁 synchronized

    存在共享数据; 多线程共同操作共享数。 synchronized 可以保证在同一时刻,只有一个线程可以执行某个方法或某个代码块,同时 synchronized 可以保证一个线程的变化可见(可见性),即可以代替 volatile。 多线程编程中,有可能会出现多个线程同时访问同一个共享、可变

    2024年02月02日
    浏览(35)
  • 【Java 并发编程】Java 线程本地变量 ThreadLocal 详解

    先一起看一下 ThreadLocal 类的官方解释: 用大白话翻译过来,大体的意思是: ThreadLoal 提供给了 线程局部变量 。同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意: 因为每个 Thread 内有自己的实例副本,且 该副本只能由当前 Thread 使用 。

    2024年02月04日
    浏览(66)
  • java并发编程 AbstractQueuedSynchronizer(AQS)详解一

    AQS在类的注释上说的已经很明白,提供一个框架,用于实现依赖先进先出(FIFO)等待队列的阻塞锁和相关同步器(信号量、事件等)。此类被设计做为大多数类型的同步器的一个有用的基础类,这些同步器依赖于单个原子int值(state字段)来表示状态。 java 并发编程系列文章

    2024年02月10日
    浏览(45)
  • Java并发编程第6讲——线程池(万字详解)

    Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池,本篇文章就详细介绍一下。 定义:线程池是一种用于管理和重用线程的技术(池化技术),它主要用于提高多线程应用程序的性能和效率。 ps:线程池、连接池、内存池

    2024年02月11日
    浏览(39)
  • 【100天精通python】Day25:python的编程方式以及并发编程详解

    目录  专栏导读  1 python的编程方式 2 顺序编程 3 面向对象编程

    2024年02月14日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包