Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

1. Introduction to Fork/Jion framework

Brief introduction to Fork/Join: It is to Fork a large task into several small tasks if necessary, and then Join the results of each small task. ForkJoin is a multi-line concurrent processing framework developed in JDK1.7. The basic idea behind ForkJoin is to divide and conquer.

Fork/Jion features: Job stealing

Note: The task queue is a dual-end queue, which can work in first-in, first-out mode or last-in, first-out mode.

2. Use of Fork/Jion

To use the ForkJoin framework or ForkJoinPool, create a ForkJoin task. ForkJoinPool provides two implementation classes for RecursiveAction and RecursiveTask.

The difference between the two implementation classes is that a RecursiveAction task does not return a value, and a RecursiveTask can have a return value.

ForkJoin example: A large amount of data is added

package com.cheng.forkjoin;

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 ForkJoinDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        //1
        long start1 = System.currentTimeMillis();
        Long sum1 = 0L;
        for (Long i = 1L; i <= 10 _0000_0000; i++) {
            sum1 += i;
        }
        long end1 = System.currentTimeMillis();
        System.out.println("Sum1 ="+sum1+", time ->"+(end1-start1));Sum1 =500000000500000000, time -> 7896


        //2. Use ForkJoin to calculate
        long start = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        SumTask task = new SumTask(1L.10_0000_0000L);
        ForkJoinTask<Long> submit = forkJoinPool.submit(task);// Submit a ForkJoinTask to the ForkJoinPool
        Long sum = submit.get();// Get the execution result
        long end = System.currentTimeMillis();
        System.out.println("ForkJoin sum="+sum+", time ->"+(end-start));Sum =500000000500000081, time -> 168

        //3. Use Stream for parallel computation
        long start2 = System.currentTimeMillis();
        long sum2 = LongStream.rangeClosed(0.10 _0000_0000)// Generate a number between 0 and 10_0000_0000
                .parallel()// Switch to a parallel stream, where a content is divided into internal blocks and each block is processed separately by a different thread
                .reduce(1, Long::sum);
        long end2 = System.currentTimeMillis();
        System.out.println(Sum ="+sum2+", time ->"+(end2-start2));//sum=500000000500000000, time -> 7406}}// Compute task class, inheriting RecursiveTask with return value
class SumTask extends RecursiveTask<Long> {

    private Long start; // The value that the subtask began to calculate
    private Long end; // The value calculated at the end of the subtask
    static final Long TEMP = 10000L;// Tasks that exceed this threshold need to be decomposed

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

    @Override
    protected Long compute(a) {
        // If this condition is true, the number of values required for the task is small enough to start the formal summation
        Long sum = 0L;
        if ((end - start) < TEMP){
            for (Long i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
            // If not, split the task into two tasks
        }else {
            Long middle = (start + end) / 2;
            SumTask task1 = new SumTask(start, middle);
            task1.fork();// Put the newly created subtask into the work queue of the current thread
            SumTask task2 = new SumTask(middle +1, end);
            task2.fork();
            return task1.join() + task2.join();// Join () waits for the subtask to complete and returns the result}}}Copy the code