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處理大數據量的優勢。

 

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