Java8新特性(三)-Fork/Join 框架和Optional 類

一,Fork/Join 框架

    就是在必要的情況下,將一個大任務,進行拆分(fork)成若干個 小任務(拆到不可再拆時),再將一個個的小任務運算的結果進行 join 彙總.

實現原理圖:

1,Fork/Join 框架與傳統線程池的區別

     採用 “工作竊取”模式(work-stealing): 當執行新的任務時它可以將其拆分分成更小的任務執行,並將小任務加到線 程隊列中,然後再從一個隨機線程的隊列中偷一個並把它放在自己的隊列中。 相對於一般的線程池實現,fork/join框架的優勢體現在對其中包含的任務的 處理方式上.在一般的線程池中,如果一個線程正在執行的任務由於某些原因 無法繼續運行,那麼該線程會處於等待狀態.而在fork/join框架實現中,如果 某個子問題由於等待另外一個子問題的完成而無法繼續運行.那麼處理該子 問題的線程會主動尋找其他尚未運行的子問題來執行.這種方式減少了線程 的等待時間,提高了性能.

 

2,並行流與串行流

並行流就是把一個內容分成多個數據塊,並用不同的線程分 別處理每個數據塊的流。 

   Java 8 中將並行進行了優化,我們可以很容易的對數據進行並 行操作。 Stream API 可以聲明性地通過 parallel() 與 sequential() 在並行流與順序流之間進行切換。

 

Fork/Join 框架代碼實現示例:

需求,給定開始值和結束值,進行累加計算

package com.atguigu.java8;

import java.util.concurrent.RecursiveTask;

public class ForkJoinCalculate extends RecursiveTask<Long>{

	/**
	 * 
	 */
	private static final long serialVersionUID = 13475679780L;
	
	private long start;
	private long end;
	
	private static final long THRESHOLD = 10000L; //臨界值
	
	public ForkJoinCalculate(long start, long end) {
		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 middle = (start + end) / 2;
			
			ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
			left.fork(); //拆分,並將該子任務壓入線程隊列
			
			ForkJoinCalculate right = new ForkJoinCalculate(middle+1, end);
			right.fork();
			
			return left.join() + right.join();
		}
		
	}

}
package com.atguigu.java8;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

import org.junit.Test;

public class TestForkJoin {
	
	@Test
	public void test1(){
		long start = System.currentTimeMillis();
		
		ForkJoinPool pool = new ForkJoinPool();
		ForkJoinTask<Long> task = new ForkJoinCalculate(0L, 10000000000L);
		
		long sum = pool.invoke(task);
		System.out.println(sum);
		
		long end = System.currentTimeMillis();
		
		System.out.println("耗費的時間爲: " + (end - start)); //112-1953-1988-2654-2647-20663-113808
	}
	
	@Test
	public void test2(){
		long start = System.currentTimeMillis();
		
		long sum = 0L;
		
		for (long i = 0L; i <= 10000000000L; i++) {
			sum += i;
		}
		
		System.out.println(sum);
		
		long end = System.currentTimeMillis();
		
		System.out.println("耗費的時間爲: " + (end - start)); //34-3174-3132-4227-4223-31583
	}
	
	@Test
	public void test3(){
		long start = System.currentTimeMillis();
		
		Long sum = LongStream.rangeClosed(0L, 10000000000L)
							 .parallel()
							 .sum();
		
		System.out.println(sum);
		
		long end = System.currentTimeMillis();
		
		System.out.println("耗費的時間爲: " + (end - start)); //2061-2053-2086-18926
	}

}

 

二,Optional 類

Optional<T> 類(java.util.Optional) 是一個容器類,代表一個值存在或不存在, 原來用 null 表示一個值不存在,現在 Optional 可以更好的表達這個概念。並且 可以避免空指針異常。 

常用方法:

Optional.of(T t) : 創建一個 Optional 實例

Optional.empty() : 創建一個空的 Optional 實例

Optional.ofNullable(T t):若 t 不爲 null,創建 Optional 實例,否則創建空實例

isPresent() : 判斷是否包含值

orElse(T t) : 如果調用對象包含值,返回該值,否則返回t

orElseGet(Supplier s) :如果調用對象包含值,返回該值,否則返回 s 獲取的值

map(Function f): 如果有值對其處理,並返回處理後的Optional,否則返回 Optional.empty()

flatMap(Function mapper):與 map 類似,要求返回值必須是Optional

 

方法使用代碼示例:

package com.atguigu.java8;

import java.util.Optional;

import org.junit.Test;

/*
 * 一、Optional 容器類:用於儘量避免空指針異常
 * 	Optional.of(T t) : 創建一個 Optional 實例
 * 	Optional.empty() : 創建一個空的 Optional 實例
 * 	Optional.ofNullable(T t):若 t 不爲 null,創建 Optional 實例,否則創建空實例
 * 	isPresent() : 判斷是否包含值
 * 	orElse(T t) :  如果調用對象包含值,返回該值,否則返回t
 * 	orElseGet(Supplier s) :如果調用對象包含值,返回該值,否則返回 s 獲取的值
 * 	map(Function f): 如果有值對其處理,並返回處理後的Optional,否則返回 Optional.empty()
 * 	flatMap(Function mapper):與 map 類似,要求返回值必須是Optional
 */
public class TestOptional {
	
	@Test
	public void test4(){
		Optional<Employee> op = Optional.of(new Employee(101, "張三", 18, 9999.99));
		
		Optional<String> op2 = op.map(Employee::getName);
		System.out.println(op2.get());
		
		Optional<String> op3 = op.flatMap((e) -> Optional.of(e.getName()));
		System.out.println(op3.get());
	}
	
	@Test
	public void test3(){
		Optional<Employee> op = Optional.ofNullable(new Employee());
		
		if(op.isPresent()){
			System.out.println(op.get());
		}
		
		Employee emp = op.orElse(new Employee("張三"));
		System.out.println(emp);
		
		Employee emp2 = op.orElseGet(() -> new Employee());
		System.out.println(emp2);
	}
	
	@Test
	public void test2(){
		/*Optional<Employee> op = Optional.ofNullable(null);
		System.out.println(op.get());*/
		
//		Optional<Employee> op = Optional.empty();
//		System.out.println(op.get());
	}

	@Test
	public void test1(){
		Optional<Employee> op = Optional.of(new Employee());
		Employee emp = op.get();
		System.out.println(emp);
	}
	
	@Test
	public void test5(){
		Man man = new Man();
		
		String name = getGodnessName(man);
		System.out.println(name);
	}
	
	//需求:獲取一個男人心中女神的名字
	public String getGodnessName(Man man){
		if(man != null){
			Godness g = man.getGod();
			
			if(g != null){
				return g.getName();
			}
		}
		
		return "蒼老師";
	}
	
	//運用 Optional 的實體類
	@Test
	public void test6(){
		Optional<Godness> godness = Optional.ofNullable(new Godness("林志玲"));
		
		Optional<NewMan> op = Optional.ofNullable(new NewMan(godness));
		String name = getGodnessName2(op);
		System.out.println(name);
	}
	
	public String getGodnessName2(Optional<NewMan> man){
		return man.orElse(new NewMan())
				  .getGodness()
				  .orElse(new Godness("蒼老師"))
				  .getName();
	}
}

 

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