ForkJoin框架——并行流与串行流

计算1-100亿累加值,并和单线程效率比较

一、ForkJoinCalculation核心类 

import java.util.concurrent.RecursiveTask;

/** 
* @ClassName: ForkJoinCalculation 
* @Description: TODO
* @author Liu 
* @date 2021年3月8日 上午8:00:14 
*/
public class ForkJoinCalculation extends RecursiveTask<Long>{//RecursiveAction<Long>不返回结果
	private Long start;
	
	private Long end;
	
	//临界值
	private static final Long THRESHOLD = 10000L;
	
	public ForkJoinCalculation(Long start, Long end) {
		super();
		this.start = start;
		this.end = end;
	}

	@Override
	protected Long compute() {
		long length = end - start;
		
		if(length <= THRESHOLD) {
			long sum = 0;
			
			for (long i = start; i <= end; i++) {
				sum += i;
			}
			
			return sum;
		}
		else {
			long mid = ( start + end ) / 2;
			
			ForkJoinCalculation left = new ForkJoinCalculation(start, mid);
			left.fork();//拆分子任务,同时压入线程队列
			
			ForkJoinCalculation right = new ForkJoinCalculation(mid + 1, end);
			right.fork();
			
			return left.join() + right.join();
		}
	}
}

二、测试

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

import org.junit.Test;

/** 
* @ClassName: ForkJoinTest 
* @Description: TODO
* @author Liu 
* @date 2021年3月8日 上午8:17:46 
*/
public class ForkJoinTest {

	/***
	 * ForkJoin框架
	 */
	@Test
	public void test() {
		Instant start = Instant.now();
		
		ForkJoinPool pool = new ForkJoinPool();
		
		//4229(100亿)-27295(500亿)
		ForkJoinTask<Long> task = new ForkJoinCalculation(1L, 50000000000L);
		
		long sum = pool.invoke(task);
		
		System.out.println(sum);
		
		Instant end = Instant.now();
		
		System.out.println(Duration.between(start, end).toMillis());
	}
	
	/***
	 * 普通for
	 */
	@Test
	public void test2() {
		Instant start = Instant.now();
		
		long sum = 0;
		
		for (long i = 0; i <= 50000000000L; i++) {
			sum += i;
		}
		
		System.out.println(sum);
		
		Instant end = Instant.now();
		
		//3391(100亿)-16869(500亿)
		System.out.println(Duration.between(start, end).toMillis());
	}
	
	/**
	 * java8并行流
	 */
	@Test
	public void test3() {
		Instant start = Instant.now();
		
		long reduce = LongStream.rangeClosed(0, 50000000000L)
				  				.reduce(0, Long :: sum);
		
		System.out.println(reduce);
		
		Instant end = Instant.now();
		
		//27629(500亿)
		System.out.println(Duration.between(start, end).toMillis());
	}
}

三、总结

        1、在数字较小范围内(如1亿),和单线程相比,可能比单线程慢;

        2、ForkJoin框架发挥作用,数字要足够大,另一个是临界值THRESHOLD要合理(偏大);

        3、重视parallel()-map-reduce处理大数据量的优势。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章