JUC-13-ForJoinPool分支/合并框架

 
 
 
工作窃取(work-stealing)算法是指某个线程从其他队列里窃取任务来执行
 
为什么ForkJoin会存在工作窃取呢?因为我们将任务进行分解成多个子任务的时候。每个子任务的处理时间都不一样。例如分别有子任务A\B。如果子任务A的1ms的时候已经执行,子任务B还在执行。那么如果我们子任务A的线程等待子任务B完毕后在进行汇总,那么子任务A线程就会在浪费执行时间,最终的执行时间就以最耗时的子任务为准。而如果我们的子任务A执行完毕后,处理子任务B的任务,并且执行完毕后将任务归还给子任务B。这样就可以提高执行效率。而这种就是工作窃取。
 
 
         
 
 
package com.wf.zhang.juc;

import org.junit.Test;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream;

public class TestForkJoinPool {
    
    public static void main(String[] args) {
        Instant start = Instant.now();
        
        ForkJoinPool pool = new ForkJoinPool();
        
        ForkJoinTask<Long> task = new ForkJoinSumCalculate(0L, 50000000000L);
        
        Long sum = pool.invoke(task);
        
        System.out.println(sum);
        
        Instant end = Instant.now();
        
        System.out.println("耗费时间为:" + Duration.between(start, end).toMillis());//166-1996-10590
    }
    
    @Test
    public void test1(){
        Instant start = Instant.now();
        
        long sum = 0L;
        
        for (long i = 0L; i <= 50000000000L; i++) {
            sum += i;
        }
        
        System.out.println(sum);
        
        Instant end = Instant.now();
        
        System.out.println("耗费时间为:" + Duration.between(start, end).toMillis());//35-3142-15704
    }
    
    //java8 新特性
    @Test
    public void test2(){
        Instant start = Instant.now();
        
        Long sum = LongStream.rangeClosed(0L, 50000000000L)
                             .parallel()
                             .reduce(0L, Long::sum);
        
        System.out.println(sum);
        
        Instant end = Instant.now();
        
        System.out.println("耗费时间为:" + Duration.between(start, end).toMillis());//1536-8118
    }

}

class ForkJoinSumCalculate extends RecursiveTask<Long>{

    private static final long serialVersionUID = -259195479995561737L;
    
    private long start;
    private long end;
    
    private static final long THURSHOLD = 10000L;  //临界值
    
    public ForkJoinSumCalculate(long start, long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long length = end - start;
        
        if(length <= THURSHOLD){
            long sum = 0L;
            
            for (long i = start; i <= end; i++) {
                sum += i;
            }
            
            return sum;
        }else{
            long middle = (start + end) / 2;
            
            ForkJoinSumCalculate left = new ForkJoinSumCalculate(start, middle); 
            left.fork(); //进行拆分,同时压入线程队列
            
            ForkJoinSumCalculate right = new ForkJoinSumCalculate(middle+1, end);
            right.fork(); //
            
            return left.join() + right.join();
        }
    }
    
}

猜你喜欢

转载自www.cnblogs.com/wf-zhang/p/12081378.html