当前位置: 首页 > article >正文

Fork/Join框架说明

目录

1.说明

2.ForkJoinPool的说明

3.ForkJoinTask的说明

4.任务的提交方式

5.示例


1.说明

Fork/Join框架使用的是分而治之的一种模式,比如常见的map reduce也是这种模式。

分而治之就是把一个很大的任务拆分成多个毫无关系的小任务,多个线程执行这些小任务。

本质上通过递归处理,将大任务进行拆分执行,如果有返回结果,将结果进行合并返回。

框架包含两个关键操作,Fork(分解)和Join(合并),适用于可以分为多个子问题的计算密集型任务,充分利用多核处理器实现多个线程并行执行,提高执行效率。

框架包含一个线程池(ForkJoinPool)和任务(ForkJoinTask)的概念。在任务内实现任务逻辑,并按照最小任务大小进行分割,然后将任务提交到线程池进行处理。

Fork/Join模式的优点在于他能够充分利用多核处理器的并行性,提高计算效率。但是也存在一些局限性,比如某些问题无法自然的拆分成独立的子任务,任务拆分的过大或者过小导致处理性能差别较大。

2.ForkJoinPool的说明

线程池的线程数默认根据cpu逻辑处理器的个数决定,可以手动设定并发执行的线程数。构造函数如下:

    // 无参构造函数:通常情况下,并发度的默认值为Runtime.availableProcessors()    
    public ForkJoinPool() {
        this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
             defaultForkJoinWorkerThreadFactory, null, false);
    }
    // 指定线程池并发度的构造函数
    public ForkJoinPool(int parallelism) {
        this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
    }
    // 以上两个public构造函数,都将调用如下构造函数
    public ForkJoinPool(int parallelism,
                        ForkJoinWorkerThreadFactory factory,
                        UncaughtExceptionHandler handler,
                        boolean asyncMode) {
        this(checkParallelism(parallelism),
             checkFactory(factory),
             handler,
             asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
             "ForkJoinPool-" + nextPoolId() + "-worker-");
        checkPermission();
    }

(1)parallelism:并行级别,通常默认为 JVM 可用的处理器个数,如下: Runtime.getRuntime().availableProcessors()

(2)factory:用于创建 ForkJoinPool 中使用的线程,ForkJoinPool管理的线程均是扩展自Thread类的ForkJoinWorkerThread类型(里面包含了一个双端队列)。如果你不指定factory,那么将由默认的DefaultForkJoinWorkerThreadFactory负责线程的创建工作。

(3)handler:用于处理工作线程未处理的异常,默认为 null。

(4)asyncMode:用于控制 WorkQueue 的工作模式。当asyncMode为true时,将使用先进先出队列,而为false时则使用后进先出的模式。默认为false,是后进先出模式。

    public static ForkJoinPool commonPool() {
        // assert common != null : "static init error";
        return common;
    }

 ForkJoinPool还提供了一个static公共池,对应ForkJoinPool中的static final变量。

ForkJoinPool提供了commonPool()方法,用于获取公共池。

任何未显式提交到指定池(如自定义的池)的ForkJoinTask,都将使用公共池进行处理。

公共池中的线程,在不使用的时候可以被缓慢回收,而后续使用时又可以恢复,因此使用公共池可以减少资源开销

LIFO及任务窃取:

工作窃取指的是当某个线程的任务队列中没有可执行的任务时,从其他线程的任务队列中来窃取任务进行执行,以充分利用工作线程的计算能力,减少线程由于获取不到任务而造成的空间浪费。在ForkJoinPool中,工作任务的队列都采用双端队列容器,通常在使用队列时,我们都是在队尾插入,而在队头消费实现FIFO,而为了工作窃取,采用的LIFO模式,在队尾插入,在队尾进行消费,工作窃取时,从队列头部获取任务进行执行,使用的是FIFO模式。

3.ForkJoinTask的说明

①有返回值的任务RecursiveTask<T>

②没有返回值的任务RecursiveAction

根据需要继承两个类中的一个,重写compute方法,在方法中进行任务的分解和合并,注意要定义好最小任务的大小。

4.任务的提交方式

①execute

提交异步执行,主线程不会等待。

②invoke

等待并获取执行结果,主线程会等待,直至获取线程的执行结果

③submit

提交执行获取Feture结果,主线程不会等待,可以通过Feture获取执行结果

5.示例

package com.test.forkjoin;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RecursiveTask;

/**
 * @Author linaibo
 * @Date 2023/11/14 11:25
 * @Version 1.0
 */
public class ForkJoinTest extends RecursiveTask<List<String>> {

    private static final int point = 10;

    private int start;
    private int end;
    private List<String> strList;

    public ForkJoinTest(int start, int end, List<String> strList) {
        this.start = start;
        this.end = end;
        this.strList = strList;
    }

    @Override
    protected List<String> compute() {
        List<String> list = new ArrayList<>();
        if ((end - start) <= point) {
            for (int i = start; i <= end; i++) {
                list.add(strList.get(i).toUpperCase());
                System.out.println("线程:" + Thread.currentThread().getName() + "执行" + i);

            }
        } else {
            int fen = (start + end) / 2;
            ForkJoinTest forkJoinTest1 = new ForkJoinTest(start, fen, strList);
            ForkJoinTest forkJoinTest2 = new ForkJoinTest(fen + 1, end, strList);
            invokeAll(forkJoinTest1, forkJoinTest2);
            List<String> join1 = forkJoinTest1.join();
            List<String> join2 = forkJoinTest2.join();
            list.addAll(join1);
            list.addAll(join2);
        }
        return list;
    }
}

①execute示例

    @Test
    public void testExecute() {
        ForkJoinPool forkJoinPool = new ForkJoinPool(8);
        List<String> strlist = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            strlist.add("qwe" + i);
        }
        ForkJoinTest forkJoinTest = new ForkJoinTest(0, strlist.size() - 1, strlist);
        forkJoinPool.execute(forkJoinTest);
        System.out.println(forkJoinPool.getPoolSize());
        System.out.println(forkJoinPool.getStealCount());
        System.out.println(forkJoinPool.getActiveThreadCount());
        System.out.println("执行完成");
    }

执行结果:

 使用execute,主线程不会等待子线程执行结束。

"C:\Program Files\Java\jdk1.8.0_241\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2021.3.3\lib\idea_rt.jar=62528:D:\Program Files\JetBrains\IntelliJ IDEA 2021.3.3\bin" -Dfile.encoding=UTF-8 -classpath "D:\Program Files\JetBrains\IntelliJ IDEA 2021.3.3\lib\idea_rt.jar;D:\Program Files\JetBrains\IntelliJ IDEA 2021.3.3\plugins\junit\lib\junit5-rt.jar;D:\Program Files\JetBrains\IntelliJ IDEA 2021.3.3\plugins\junit\lib\junit-rt.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_241\jre\lib\rt.jar;E:\learn\lintest\esyexce-poi\target\test-classes;E:\learn\lintest\esyexce-poi\target\classes;D:\myMaven\repo\com\aliyun\alibaba-dingtalk-service-sdk\2.0.0\alibaba-dingtalk-service-sdk-2.0.0.jar;D:\myMaven\repo\log4j\log4j\1.2.15\log4j-1.2.15.jar;D:\myMaven\repo\javax\mail\mail\1.4\mail-1.4.jar;D:\myMaven\repo\javax\activation\activation\1.1\activation-1.1.jar;D:\myMaven\repo\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;D:\myMaven\repo\org\springframework\boot\spring-boot-starter\2.3.4.RELEASE\spring-boot-starter-2.3.4.RELEASE.jar;D:\myMaven\repo\org\springframework\boot\spring-boot\2.3.4.RELEASE\spring-boot-2.3.4.RELEASE.jar;D:\myMaven\repo\org\springframework\spring-context\5.2.9.RELEASE\spring-context-5.2.9.RELEASE.jar;D:\myMaven\repo\org\springframework\boot\spring-boot-autoconfigure\2.3.4.RELEASE\spring-boot-autoconfigure-2.3.4.RELEASE.jar;D:\myMaven\repo\org\springframework\boot\spring-boot-starter-logging\2.3.4.RELEASE\spring-boot-starter-logging-2.3.4.RELEASE.jar;D:\myMaven\repo\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\myMaven\repo\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\myMaven\repo\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;D:\myMaven\repo\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;D:\myMaven\repo\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;D:\myMaven\repo\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\myMaven\repo\org\springframework\spring-core\5.2.9.RELEASE\spring-core-5.2.9.RELEASE.jar;D:\myMaven\repo\org\springframework\spring-jcl\5.2.9.RELEASE\spring-jcl-5.2.9.RELEASE.jar;D:\myMaven\repo\org\yaml\snakeyaml\1.26\snakeyaml-1.26.jar;D:\myMaven\repo\org\springframework\boot\spring-boot-starter-web\2.5.15\spring-boot-starter-web-2.5.15.jar;D:\myMaven\repo\org\springframework\boot\spring-boot-starter-json\2.5.15\spring-boot-starter-json-2.5.15.jar;D:\myMaven\repo\com\fasterxml\jackson\core\jackson-databind\2.12.7.1\jackson-databind-2.12.7.1.jar;D:\myMaven\repo\com\fasterxml\jackson\core\jackson-annotations\2.12.7\jackson-annotations-2.12.7.jar;D:\myMaven\repo\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.12.7\jackson-datatype-jdk8-2.12.7.jar;D:\myMaven\repo\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.12.7\jackson-datatype-jsr310-2.12.7.jar;D:\myMaven\repo\com\fasterxml\jackson\module\jackson-module-parameter-names\2.12.7\jackson-module-parameter-names-2.12.7.jar;D:\myMaven\repo\org\springframework\boot\spring-boot-starter-tomcat\2.5.15\spring-boot-starter-tomcat-2.5.15.jar;D:\myMaven\repo\org\apache\tomcat\embed\tomcat-embed-core\9.0.75\tomcat-embed-core-9.0.75.jar;D:\myMaven\repo\org\apache\tomcat\embed\tomcat-embed-el\9.0.75\tomcat-embed-el-9.0.75.jar;D:\myMaven\repo\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.75\tomcat-embed-websocket-9.0.75.jar;D:\myMaven\repo\org\springframework\spring-web\5.3.27\spring-web-5.3.27.jar;D:\myMaven\repo\org\springframework\spring-beans\5.3.27\spring-beans-5.3.27.jar;D:\myMaven\repo\org\springframework\spring-webmvc\5.3.27\spring-webmvc-5.3.27.jar;D:\myMaven\repo\org\springframework\spring-aop\5.3.27\spring-aop-5.3.27.jar;D:\myMaven\repo\org\springframework\spring-expression\5.3.27\spring-expression-5.3.27.jar;D:\myMaven\repo\com\alibaba\boot\nacos-config-spring-boot-starter\0.2.5\nacos-config-spring-boot-starter-0.2.5.jar;D:\myMaven\repo\com\alibaba\nacos\nacos-spring-context\1.1.0\nacos-spring-context-1.1.0.jar;D:\myMaven\repo\javax\annotation\javax.annotation-api\1.3.2\javax.annotation-api-1.3.2.jar;D:\myMaven\repo\org\apache\commons\commons-lang3\3.4\commons-lang3-3.4.jar;D:\myMaven\repo\com\alibaba\spring\spring-context-support\1.0.11\spring-context-support-1.0.11.jar;D:\myMaven\repo\com\alibaba\nacos\nacos-client\1.4.2\nacos-client-1.4.2.jar;D:\myMaven\repo\com\alibaba\nacos\nacos-common\1.4.2\nacos-common-1.4.2.jar;D:\myMaven\repo\commons-io\commons-io\2.7\commons-io-2.7.jar;D:\myMaven\repo\org\apache\httpcomponents\httpasyncclient\4.1.3\httpasyncclient-4.1.3.jar;D:\myMaven\repo\org\apache\httpcomponents\httpcore\4.4.6\httpcore-4.4.6.jar;D:\myMaven\repo\org\apache\httpcomponents\httpcore-nio\4.4.6\httpcore-nio-4.4.6.jar;D:\myMaven\repo\org\apache\httpcomponents\httpclient\4.5.3\httpclient-4.5.3.jar;D:\myMaven\repo\com\alibaba\nacos\nacos-api\1.4.2\nacos-api-1.4.2.jar;D:\myMaven\repo\com\google\guava\guava\30.1-jre\guava-30.1-jre.jar;D:\myMaven\repo\com\google\guava\failureaccess\1.0.1\failureaccess-1.0.1.jar;D:\myMaven\repo\com\google\guava\listenablefuture\9999.0-empty-to-avoid-conflict-with-guava\listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar;D:\myMaven\repo\com\google\code\findbugs\jsr305\3.0.2\jsr305-3.0.2.jar;D:\myMaven\repo\org\checkerframework\checker-qual\3.5.0\checker-qual-3.5.0.jar;D:\myMaven\repo\com\google\errorprone\error_prone_annotations\2.3.4\error_prone_annotations-2.3.4.jar;D:\myMaven\repo\com\google\j2objc\j2objc-annotations\1.3\j2objc-annotations-1.3.jar;D:\myMaven\repo\commons-codec\commons-codec\1.11\commons-codec-1.11.jar;D:\myMaven\repo\com\fasterxml\jackson\core\jackson-core\2.12.2\jackson-core-2.12.2.jar;D:\myMaven\repo\io\prometheus\simpleclient\0.5.0\simpleclient-0.5.0.jar;D:\myMaven\repo\com\alibaba\boot\nacos-config-spring-boot-autoconfigure\0.2.5\nacos-config-spring-boot-autoconfigure-0.2.5.jar;D:\myMaven\repo\com\alibaba\boot\nacos-spring-boot-base\0.2.5\nacos-spring-boot-base-0.2.5.jar;D:\myMaven\repo\com\alibaba\easyexcel\2.2.6\easyexcel-2.2.6.jar;D:\myMaven\repo\org\apache\poi\poi\3.17\poi-3.17.jar;D:\myMaven\repo\org\apache\commons\commons-collections4\4.1\commons-collections4-4.1.jar;D:\myMaven\repo\org\apache\poi\poi-ooxml-schemas\3.17\poi-ooxml-schemas-3.17.jar;D:\myMaven\repo\org\apache\xmlbeans\xmlbeans\2.6.0\xmlbeans-2.6.0.jar;D:\myMaven\repo\stax\stax-api\1.0.1\stax-api-1.0.1.jar;D:\myMaven\repo\cglib\cglib\3.1\cglib-3.1.jar;D:\myMaven\repo\org\ow2\asm\asm\4.2\asm-4.2.jar;D:\myMaven\repo\org\slf4j\slf4j-api\1.7.26\slf4j-api-1.7.26.jar;D:\myMaven\repo\org\ehcache\ehcache\3.4.0\ehcache-3.4.0.jar;D:\myMaven\repo\org\apache\poi\poi-ooxml\3.17\poi-ooxml-3.17.jar;D:\myMaven\repo\com\github\virtuald\curvesapi\1.04\curvesapi-1.04.jar;D:\myMaven\repo\org\projectlombok\lombok\1.18.28\lombok-1.18.28.jar;D:\myMaven\repo\com\alibaba\fastjson2\fastjson2\2.0.34\fastjson2-2.0.34.jar;D:\myMaven\repo\junit\junit\4.12\junit-4.12.jar;D:\myMaven\repo\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 easyTest,testExecute
1
0
1
执行完成
线程:ForkJoinPool-1-worker-1执行0
线程:ForkJoinPool-1-worker-1执行1
线程:ForkJoinPool-1-worker-1执行2
线程:ForkJoinPool-1-worker-1执行3
线程:ForkJoinPool-1-worker-1执行4
线程:ForkJoinPool-1-worker-1执行5
线程:ForkJoinPool-1-worker-1执行6
线程:ForkJoinPool-1-worker-1执行7
线程:ForkJoinPool-1-worker-1执行8
线程:ForkJoinPool-1-worker-1执行9
线程:ForkJoinPool-1-worker-1执行10
线程:ForkJoinPool-1-worker-1执行11
线程:ForkJoinPool-1-worker-1执行12
线程:ForkJoinPool-1-worker-2执行50
线程:ForkJoinPool-1-worker-2执行51
线程:ForkJoinPool-1-worker-2执行52
线程:ForkJoinPool-1-worker-3执行25
线程:ForkJoinPool-1-worker-1执行13
线程:ForkJoinPool-1-worker-3执行26
线程:ForkJoinPool-1-worker-2执行53
线程:ForkJoinPool-1-worker-3执行27
线程:ForkJoinPool-1-worker-1执行14
线程:ForkJoinPool-1-worker-1执行15
线程:ForkJoinPool-1-worker-3执行28
线程:ForkJoinPool-1-worker-3执行29
线程:ForkJoinPool-1-worker-3执行30
线程:ForkJoinPool-1-worker-4执行75
线程:ForkJoinPool-1-worker-4执行76
线程:ForkJoinPool-1-worker-5执行19
线程:ForkJoinPool-1-worker-5执行20
线程:ForkJoinPool-1-worker-2执行54
线程:ForkJoinPool-1-worker-5执行21
线程:ForkJoinPool-1-worker-0执行88
线程:ForkJoinPool-1-worker-0执行89
线程:ForkJoinPool-1-worker-0执行90
线程:ForkJoinPool-1-worker-0执行91
线程:ForkJoinPool-1-worker-0执行92
线程:ForkJoinPool-1-worker-0执行93
线程:ForkJoinPool-1-worker-0执行94
线程:ForkJoinPool-1-worker-0执行95
线程:ForkJoinPool-1-worker-0执行96
线程:ForkJoinPool-1-worker-0执行97
线程:ForkJoinPool-1-worker-0执行98
线程:ForkJoinPool-1-worker-0执行99
线程:ForkJoinPool-1-worker-0执行82
线程:ForkJoinPool-1-worker-0执行83
线程:ForkJoinPool-1-worker-0执行84
线程:ForkJoinPool-1-worker-0执行85
线程:ForkJoinPool-1-worker-0执行86
线程:ForkJoinPool-1-worker-0执行87
线程:ForkJoinPool-1-worker-4执行77
线程:ForkJoinPool-1-worker-6执行38
线程:ForkJoinPool-1-worker-3执行31

Process finished with exit code 0
线程:ForkJoinPool-1-worker-1执行16

②invoke方式

    @Test
    public void test() {
        ForkJoinPool forkJoinPool = new ForkJoinPool(8);
        List<String> strlist = new ArrayList<>();
        for (int i = 0; i < 200; i++) {
            strlist.add("qwe" + i);
        }
        ForkJoinTest forkJoinTest = new ForkJoinTest(0, strlist.size() - 1, strlist);
        List<String> list = forkJoinPool.invoke(forkJoinTest);
        System.out.println(forkJoinPool.getPoolSize());
        System.out.println(forkJoinPool.getStealCount());
        System.out.println(forkJoinPool.getActiveThreadCount());
        System.out.println("执行完成");
        System.out.println(JSON.toJSONString(list));
        forkJoinPool.shutdown();
    }

执行结果

先执行子线程,子线程执行完成之后,进行主线程处理,这是最常用的方式。

线程:ForkJoinPool-1-worker-1执行0
线程:ForkJoinPool-1-worker-1执行1
线程:ForkJoinPool-1-worker-1执行2
线程:ForkJoinPool-1-worker-1执行3
线程:ForkJoinPool-1-worker-1执行4
线程:ForkJoinPool-1-worker-1执行5
线程:ForkJoinPool-1-worker-1执行6
线程:ForkJoinPool-1-worker-1执行7
线程:ForkJoinPool-1-worker-1执行8
线程:ForkJoinPool-1-worker-1执行9
线程:ForkJoinPool-1-worker-1执行10
线程:ForkJoinPool-1-worker-1执行11
线程:ForkJoinPool-1-worker-3执行100
线程:ForkJoinPool-1-worker-5执行25
线程:ForkJoinPool-1-worker-5执行26
线程:ForkJoinPool-1-worker-5执行27
线程:ForkJoinPool-1-worker-5执行28
线程:ForkJoinPool-1-worker-2执行50
线程:ForkJoinPool-1-worker-1执行12
线程:ForkJoinPool-1-worker-2执行51
线程:ForkJoinPool-1-worker-1执行13
线程:ForkJoinPool-1-worker-5执行29
线程:ForkJoinPool-1-worker-4执行75
线程:ForkJoinPool-1-worker-7执行19
线程:ForkJoinPool-1-worker-3执行101
线程:ForkJoinPool-1-worker-3执行102
线程:ForkJoinPool-1-worker-7执行20
线程:ForkJoinPool-1-worker-7执行21
线程:ForkJoinPool-1-worker-7执行22
线程:ForkJoinPool-1-worker-7执行23
线程:ForkJoinPool-1-worker-7执行24
线程:ForkJoinPool-1-worker-4执行76
线程:ForkJoinPool-1-worker-7执行175
线程:ForkJoinPool-1-worker-5执行30
线程:ForkJoinPool-1-worker-5执行31
线程:ForkJoinPool-1-worker-5执行32
线程:ForkJoinPool-1-worker-5执行33
线程:ForkJoinPool-1-worker-1执行14
线程:ForkJoinPool-1-worker-2执行52
线程:ForkJoinPool-1-worker-1执行15
线程:ForkJoinPool-1-worker-7执行176
线程:ForkJoinPool-1-worker-4执行77
线程:ForkJoinPool-1-worker-6执行150
线程:ForkJoinPool-1-worker-6执行151
线程:ForkJoinPool-1-worker-6执行152
线程:ForkJoinPool-1-worker-6执行153
线程:ForkJoinPool-1-worker-6执行154
线程:ForkJoinPool-1-worker-3执行103
线程:ForkJoinPool-1-worker-0执行88
线程:ForkJoinPool-1-worker-3执行104
线程:ForkJoinPool-1-worker-3执行105
线程:ForkJoinPool-1-worker-3执行106
线程:ForkJoinPool-1-worker-6执行155
线程:ForkJoinPool-1-worker-4执行78
线程:ForkJoinPool-1-worker-4执行79
线程:ForkJoinPool-1-worker-7执行177
线程:ForkJoinPool-1-worker-5执行34
线程:ForkJoinPool-1-worker-1执行16
线程:ForkJoinPool-1-worker-2执行53
线程:ForkJoinPool-1-worker-1执行17
线程:ForkJoinPool-1-worker-1执行18
线程:ForkJoinPool-1-worker-5执行35
线程:ForkJoinPool-1-worker-7执行178
线程:ForkJoinPool-1-worker-4执行80
线程:ForkJoinPool-1-worker-6执行156
线程:ForkJoinPool-1-worker-3执行107
线程:ForkJoinPool-1-worker-3执行108
线程:ForkJoinPool-1-worker-3执行109
线程:ForkJoinPool-1-worker-3执行110
线程:ForkJoinPool-1-worker-3执行111
线程:ForkJoinPool-1-worker-3执行112
线程:ForkJoinPool-1-worker-0执行89
线程:ForkJoinPool-1-worker-3执行113
线程:ForkJoinPool-1-worker-6执行157
线程:ForkJoinPool-1-worker-6执行158
线程:ForkJoinPool-1-worker-4执行81
线程:ForkJoinPool-1-worker-7执行179
线程:ForkJoinPool-1-worker-5执行36
线程:ForkJoinPool-1-worker-5执行37
线程:ForkJoinPool-1-worker-1执行38
线程:ForkJoinPool-1-worker-2执行54
线程:ForkJoinPool-1-worker-2执行55
线程:ForkJoinPool-1-worker-2执行56
线程:ForkJoinPool-1-worker-2执行57
线程:ForkJoinPool-1-worker-2执行58
线程:ForkJoinPool-1-worker-2执行59
线程:ForkJoinPool-1-worker-2执行60
线程:ForkJoinPool-1-worker-2执行61
线程:ForkJoinPool-1-worker-2执行62
线程:ForkJoinPool-1-worker-2执行63
线程:ForkJoinPool-1-worker-2执行64
线程:ForkJoinPool-1-worker-2执行65
线程:ForkJoinPool-1-worker-2执行66
线程:ForkJoinPool-1-worker-2执行67
线程:ForkJoinPool-1-worker-2执行68
线程:ForkJoinPool-1-worker-5执行44
线程:ForkJoinPool-1-worker-7执行180
线程:ForkJoinPool-1-worker-7执行181
线程:ForkJoinPool-1-worker-4执行82
线程:ForkJoinPool-1-worker-6执行159
线程:ForkJoinPool-1-worker-3执行114
线程:ForkJoinPool-1-worker-0执行90
线程:ForkJoinPool-1-worker-0执行91
线程:ForkJoinPool-1-worker-0执行92
线程:ForkJoinPool-1-worker-0执行93
线程:ForkJoinPool-1-worker-3执行115
线程:ForkJoinPool-1-worker-6执行160
线程:ForkJoinPool-1-worker-4执行83
线程:ForkJoinPool-1-worker-7执行182
线程:ForkJoinPool-1-worker-7执行183
线程:ForkJoinPool-1-worker-7执行184
线程:ForkJoinPool-1-worker-7执行185
线程:ForkJoinPool-1-worker-7执行186
线程:ForkJoinPool-1-worker-7执行187
线程:ForkJoinPool-1-worker-5执行45
线程:ForkJoinPool-1-worker-5执行46
线程:ForkJoinPool-1-worker-5执行47
线程:ForkJoinPool-1-worker-5执行48
线程:ForkJoinPool-1-worker-5执行49
线程:ForkJoinPool-1-worker-2执行69
线程:ForkJoinPool-1-worker-1执行39
线程:ForkJoinPool-1-worker-1执行40
线程:ForkJoinPool-1-worker-1执行41
线程:ForkJoinPool-1-worker-2执行70
线程:ForkJoinPool-1-worker-2执行71
线程:ForkJoinPool-1-worker-1执行42
线程:ForkJoinPool-1-worker-7执行188
线程:ForkJoinPool-1-worker-4执行84
线程:ForkJoinPool-1-worker-4执行85
线程:ForkJoinPool-1-worker-4执行86
线程:ForkJoinPool-1-worker-4执行87
线程:ForkJoinPool-1-worker-6执行161
线程:ForkJoinPool-1-worker-6执行162
线程:ForkJoinPool-1-worker-6执行163
线程:ForkJoinPool-1-worker-6执行164
线程:ForkJoinPool-1-worker-6执行165
线程:ForkJoinPool-1-worker-6执行166
线程:ForkJoinPool-1-worker-6执行167
线程:ForkJoinPool-1-worker-6执行168
线程:ForkJoinPool-1-worker-3执行116
线程:ForkJoinPool-1-worker-0执行94
线程:ForkJoinPool-1-worker-3执行117
线程:ForkJoinPool-1-worker-6执行169
线程:ForkJoinPool-1-worker-7执行189
线程:ForkJoinPool-1-worker-7执行190
线程:ForkJoinPool-1-worker-7执行191
线程:ForkJoinPool-1-worker-7执行192
线程:ForkJoinPool-1-worker-7执行193
线程:ForkJoinPool-1-worker-1执行43
线程:ForkJoinPool-1-worker-2执行72
线程:ForkJoinPool-1-worker-7执行194
线程:ForkJoinPool-1-worker-6执行170
线程:ForkJoinPool-1-worker-3执行118
线程:ForkJoinPool-1-worker-0执行95
线程:ForkJoinPool-1-worker-3执行119
线程:ForkJoinPool-1-worker-3执行120
线程:ForkJoinPool-1-worker-3执行121
线程:ForkJoinPool-1-worker-3执行122
线程:ForkJoinPool-1-worker-3执行123
线程:ForkJoinPool-1-worker-3执行124
线程:ForkJoinPool-1-worker-6执行171
线程:ForkJoinPool-1-worker-7执行195
线程:ForkJoinPool-1-worker-7执行196
线程:ForkJoinPool-1-worker-7执行197
线程:ForkJoinPool-1-worker-7执行198
线程:ForkJoinPool-1-worker-7执行199
线程:ForkJoinPool-1-worker-5执行125
线程:ForkJoinPool-1-worker-7执行144
线程:ForkJoinPool-1-worker-7执行145
线程:ForkJoinPool-1-worker-7执行146
线程:ForkJoinPool-1-worker-7执行147
线程:ForkJoinPool-1-worker-7执行148
线程:ForkJoinPool-1-worker-7执行149
线程:ForkJoinPool-1-worker-2执行73
线程:ForkJoinPool-1-worker-7执行132
线程:ForkJoinPool-1-worker-7执行133
线程:ForkJoinPool-1-worker-7执行134
线程:ForkJoinPool-1-worker-7执行135
线程:ForkJoinPool-1-worker-7执行136
线程:ForkJoinPool-1-worker-7执行137
线程:ForkJoinPool-1-worker-5执行126
线程:ForkJoinPool-1-worker-5执行127
线程:ForkJoinPool-1-worker-5执行128
线程:ForkJoinPool-1-worker-5执行129
线程:ForkJoinPool-1-worker-6执行172
线程:ForkJoinPool-1-worker-3执行138
线程:ForkJoinPool-1-worker-0执行96
线程:ForkJoinPool-1-worker-0执行97
线程:ForkJoinPool-1-worker-0执行98
线程:ForkJoinPool-1-worker-0执行99
线程:ForkJoinPool-1-worker-3执行139
线程:ForkJoinPool-1-worker-6执行173
线程:ForkJoinPool-1-worker-5执行130
线程:ForkJoinPool-1-worker-2执行74
线程:ForkJoinPool-1-worker-5执行131
线程:ForkJoinPool-1-worker-6执行174
线程:ForkJoinPool-1-worker-3执行140
线程:ForkJoinPool-1-worker-3执行141
线程:ForkJoinPool-1-worker-3执行142
线程:ForkJoinPool-1-worker-3执行143
8
12
0
执行完成
["QWE0","QWE1","QWE2","QWE3","QWE4","QWE5","QWE6","QWE7","QWE8","QWE9","QWE10","QWE11","QWE12","QWE13","QWE14","QWE15","QWE16","QWE17","QWE18","QWE19","QWE20","QWE21","QWE22","QWE23","QWE24","QWE25","QWE26","QWE27","QWE28","QWE29","QWE30","QWE31","QWE32","QWE33","QWE34","QWE35","QWE36","QWE37","QWE38","QWE39","QWE40","QWE41","QWE42","QWE43","QWE44","QWE45","QWE46","QWE47","QWE48","QWE49","QWE50","QWE51","QWE52","QWE53","QWE54","QWE55","QWE56","QWE57","QWE58","QWE59","QWE60","QWE61","QWE62","QWE63","QWE64","QWE65","QWE66","QWE67","QWE68","QWE69","QWE70","QWE71","QWE72","QWE73","QWE74","QWE75","QWE76","QWE77","QWE78","QWE79","QWE80","QWE81","QWE82","QWE83","QWE84","QWE85","QWE86","QWE87","QWE88","QWE89","QWE90","QWE91","QWE92","QWE93","QWE94","QWE95","QWE96","QWE97","QWE98","QWE99","QWE100","QWE101","QWE102","QWE103","QWE104","QWE105","QWE106","QWE107","QWE108","QWE109","QWE110","QWE111","QWE112","QWE113","QWE114","QWE115","QWE116","QWE117","QWE118","QWE119","QWE120","QWE121","QWE122","QWE123","QWE124","QWE125","QWE126","QWE127","QWE128","QWE129","QWE130","QWE131","QWE132","QWE133","QWE134","QWE135","QWE136","QWE137","QWE138","QWE139","QWE140","QWE141","QWE142","QWE143","QWE144","QWE145","QWE146","QWE147","QWE148","QWE149","QWE150","QWE151","QWE152","QWE153","QWE154","QWE155","QWE156","QWE157","QWE158","QWE159","QWE160","QWE161","QWE162","QWE163","QWE164","QWE165","QWE166","QWE167","QWE168","QWE169","QWE170","QWE171","QWE172","QWE173","QWE174","QWE175","QWE176","QWE177","QWE178","QWE179","QWE180","QWE181","QWE182","QWE183","QWE184","QWE185","QWE186","QWE187","QWE188","QWE189","QWE190","QWE191","QWE192","QWE193","QWE194","QWE195","QWE196","QWE197","QWE198","QWE199"]

③submit方式

    @Test
    public void testSubmit() throws ExecutionException, InterruptedException {
        ForkJoinPool forkJoinPool = new ForkJoinPool(8);
        List<String> strlist = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            strlist.add("qwe" + i);
        }
        ForkJoinTest forkJoinTest = new ForkJoinTest(0, strlist.size() - 1, strlist);
        ForkJoinTask<List<String>> submit = forkJoinPool.submit(forkJoinTest);
        System.out.println(forkJoinPool.getPoolSize());
        System.out.println(forkJoinPool.getStealCount());
        System.out.println(forkJoinPool.getActiveThreadCount());
        System.out.println(submit.get());
        System.out.println("执行完成");
    }

执行结果

主线程不会等待,执行get方法时,会等待子线程执行完成。

1
0
1
线程:ForkJoinPool-1-worker-1执行0
线程:ForkJoinPool-1-worker-1执行1
线程:ForkJoinPool-1-worker-1执行2
线程:ForkJoinPool-1-worker-1执行3
线程:ForkJoinPool-1-worker-1执行4
线程:ForkJoinPool-1-worker-1执行5
线程:ForkJoinPool-1-worker-1执行6
线程:ForkJoinPool-1-worker-1执行7
线程:ForkJoinPool-1-worker-1执行8
线程:ForkJoinPool-1-worker-1执行9
线程:ForkJoinPool-1-worker-1执行10
线程:ForkJoinPool-1-worker-1执行11
线程:ForkJoinPool-1-worker-1执行12
线程:ForkJoinPool-1-worker-3执行25
线程:ForkJoinPool-1-worker-3执行26
线程:ForkJoinPool-1-worker-4执行75
线程:ForkJoinPool-1-worker-4执行76
线程:ForkJoinPool-1-worker-2执行50
线程:ForkJoinPool-1-worker-3执行27
线程:ForkJoinPool-1-worker-5执行19
线程:ForkJoinPool-1-worker-6执行38
线程:ForkJoinPool-1-worker-2执行51
线程:ForkJoinPool-1-worker-1执行13
线程:ForkJoinPool-1-worker-4执行77
线程:ForkJoinPool-1-worker-0执行88
线程:ForkJoinPool-1-worker-1执行14
线程:ForkJoinPool-1-worker-7执行63
线程:ForkJoinPool-1-worker-2执行52
线程:ForkJoinPool-1-worker-6执行39
线程:ForkJoinPool-1-worker-5执行20
线程:ForkJoinPool-1-worker-3执行28
线程:ForkJoinPool-1-worker-5执行21
线程:ForkJoinPool-1-worker-6执行40
线程:ForkJoinPool-1-worker-2执行53
线程:ForkJoinPool-1-worker-7执行64
线程:ForkJoinPool-1-worker-1执行15
线程:ForkJoinPool-1-worker-0执行89
线程:ForkJoinPool-1-worker-4执行78
线程:ForkJoinPool-1-worker-0执行90
线程:ForkJoinPool-1-worker-1执行16
线程:ForkJoinPool-1-worker-7执行65
线程:ForkJoinPool-1-worker-2执行54
线程:ForkJoinPool-1-worker-6执行41
线程:ForkJoinPool-1-worker-5执行22
线程:ForkJoinPool-1-worker-3执行29
线程:ForkJoinPool-1-worker-5执行23
线程:ForkJoinPool-1-worker-6执行42
线程:ForkJoinPool-1-worker-2执行55
线程:ForkJoinPool-1-worker-7执行66
线程:ForkJoinPool-1-worker-1执行17
线程:ForkJoinPool-1-worker-0执行91
线程:ForkJoinPool-1-worker-4执行79
线程:ForkJoinPool-1-worker-0执行92
线程:ForkJoinPool-1-worker-0执行93
线程:ForkJoinPool-1-worker-1执行18
线程:ForkJoinPool-1-worker-7执行67
线程:ForkJoinPool-1-worker-2执行56
线程:ForkJoinPool-1-worker-2执行57
线程:ForkJoinPool-1-worker-6执行43
线程:ForkJoinPool-1-worker-5执行24
线程:ForkJoinPool-1-worker-3执行30
线程:ForkJoinPool-1-worker-5执行69
线程:ForkJoinPool-1-worker-6执行44
线程:ForkJoinPool-1-worker-6执行45
线程:ForkJoinPool-1-worker-6执行46
线程:ForkJoinPool-1-worker-6执行47
线程:ForkJoinPool-1-worker-6执行48
线程:ForkJoinPool-1-worker-6执行49
线程:ForkJoinPool-1-worker-2执行58
线程:ForkJoinPool-1-worker-7执行68
线程:ForkJoinPool-1-worker-0执行94
线程:ForkJoinPool-1-worker-4执行80
线程:ForkJoinPool-1-worker-0执行95
线程:ForkJoinPool-1-worker-2执行59
线程:ForkJoinPool-1-worker-6执行82
线程:ForkJoinPool-1-worker-5执行70
线程:ForkJoinPool-1-worker-1执行32
线程:ForkJoinPool-1-worker-3执行31
线程:ForkJoinPool-1-worker-1执行33
线程:ForkJoinPool-1-worker-1执行34
线程:ForkJoinPool-1-worker-5执行71
线程:ForkJoinPool-1-worker-6执行83
线程:ForkJoinPool-1-worker-2执行60
线程:ForkJoinPool-1-worker-0执行96
线程:ForkJoinPool-1-worker-4执行81
线程:ForkJoinPool-1-worker-0执行97
线程:ForkJoinPool-1-worker-0执行98
线程:ForkJoinPool-1-worker-0执行99
线程:ForkJoinPool-1-worker-2执行61
线程:ForkJoinPool-1-worker-2执行62
线程:ForkJoinPool-1-worker-6执行84
线程:ForkJoinPool-1-worker-5执行72
线程:ForkJoinPool-1-worker-1执行35
线程:ForkJoinPool-1-worker-5执行73
线程:ForkJoinPool-1-worker-6执行85
线程:ForkJoinPool-1-worker-5执行74
线程:ForkJoinPool-1-worker-1执行36
线程:ForkJoinPool-1-worker-1执行37
线程:ForkJoinPool-1-worker-6执行86
线程:ForkJoinPool-1-worker-6执行87
[QWE0, QWE1, QWE2, QWE3, QWE4, QWE5, QWE6, QWE7, QWE8, QWE9, QWE10, QWE11, QWE12, QWE13, QWE14, QWE15, QWE16, QWE17, QWE18, QWE19, QWE20, QWE21, QWE22, QWE23, QWE24, QWE25, QWE26, QWE27, QWE28, QWE29, QWE30, QWE31, QWE32, QWE33, QWE34, QWE35, QWE36, QWE37, QWE38, QWE39, QWE40, QWE41, QWE42, QWE43, QWE44, QWE45, QWE46, QWE47, QWE48, QWE49, QWE50, QWE51, QWE52, QWE53, QWE54, QWE55, QWE56, QWE57, QWE58, QWE59, QWE60, QWE61, QWE62, QWE63, QWE64, QWE65, QWE66, QWE67, QWE68, QWE69, QWE70, QWE71, QWE72, QWE73, QWE74, QWE75, QWE76, QWE77, QWE78, QWE79, QWE80, QWE81, QWE82, QWE83, QWE84, QWE85, QWE86, QWE87, QWE88, QWE89, QWE90, QWE91, QWE92, QWE93, QWE94, QWE95, QWE96, QWE97, QWE98, QWE99]
执行完成


http://www.kler.cn/news/133870.html

相关文章:

  • OpenAI Assistants-API简明教程
  • 【人工智能Ⅰ】7-KNN 决策树
  • C复习-输入输出函数+流
  • MyBatis整合Spring Boot扫描Mapper相关配置
  • 在Ubuntu上用sane api实现通用扫描功能
  • Python OpenCV调整图像亮度对比度及RGB色彩
  • C++ ,VCPKG那些事
  • Linux终端与交互式Bash
  • 【数据分享】2023年我国省市县三级的独角兽企业数量(Excel/Shp格式)
  • 23111709[含文档+PPT+源码等]计算机毕业设计基于Spring Boot智能无人仓库管理-进销存储
  • 深度学习入门(第二天)——走进深度学习的世界 神经网络模型
  • 中级程序员——vue3+js+git面试题
  • 汽车虚拟仿真视频数据理解--CLIP模型原理
  • 【华为OD机试高分必刷题目】洗衣服(JavaPythonC++贪心算法实现)
  • 【数据结构(二)】单链表(3)
  • 三天吃透Redis面试八股文
  • ChatGPT之父被OpenAI解雇
  • 重生之我是一名程序员 35
  • map与set的封装
  • 【华为OD题库-027】代码编辑器-java
  • 设计模式-中介者模式-笔记
  • Perl的LWP::UserAgent库爬虫程序怎么写
  • 超大规模和隐私保护,融云如何助力 Web3 社交
  • C++ 20类型转换指南:使用场景与最佳实践
  • 软考小记-软件工程
  • 【LeetCode刷题-树】--654.最大二叉树
  • MySQL数据库索引以及使用唯一索引实现幂等性
  • 网络层——IP协议
  • 数据结构:红黑树讲解(C++)
  • Nginx负载均衡机制及常见问题