天天看點

java jdk 8學習筆記_java8學習筆記總結(五)

Lambda表達式

自Java1.0以來,已經增加了許多功能,其中兩個最為突出,對java語言産生了深遠影響,從根本上改變了代碼的編寫方式。第一是JDK5增加的泛型,第二是Lambda表達式

Lambda表達式是JDK8新增加的功能,它顯著增強了Java,原因有兩個.一,它們增加了新的文法元素,使java語言的表達能力得以提升,并流線化一些常用結構的實作方式;二,導緻API庫增加了新的功能,包括利用多核環境并行處理功能(尤其是處理for-earch風格)變得更加容易,以及支援對資料執行管道操作的新的流API.催生了新的Java功能,預設方法。

幾年前泛型重塑了java,如今lambda表達式正在重塑java

了解lambda表達式的java實作,兩個結構十分關鍵:第一lambda表達式自身,第二函數式接口

Lambda表達式本身就是一個匿名方法。但是這個方法不是獨立執行的,而是用于實作由函數式接口定義的另一個方法,是以,lambda表達式會導緻産生一個獨立匿名類。Lambda表達式也常被稱為閉包

函數式接口是僅包含一個抽象方法的接口。這個方法指明了接口的目标用途。函數式接口通常表示單個動作。例如Runnable是一個函數式接口。此外函數式接口定義了lambda表達式的目标類型。有時被稱為SAM類型,單抽象方法(Single Abstracted Method)

Lambda表達式在Java語言中引入了操作符->,它将lambda表達式分為兩個部分。左側lambda表達式需要的所有參數(可以為空),右側指定lambda體,表達式要執行的動作。

兩種lambda體。一種包含單個表達式,另一種包含一個代碼塊。

從JDK8開始,可以為接口聲明的方法指定預設行為,即預設方法。隻有當沒有指定預設實作時,接口方法才是抽象方法。

Lambda表達式不是獨立執行的,而是構成了一個函數式接口定義的抽象方法的實作,該函數式接口定義了它的目标類型。隻有在定義裡lambda表達式的目标類型的上下文中,才能使用該表達式。當把lambda表達式賦給一個函數式接口引用時,就建立了這樣的上下文。

Lambda表達式提供了一種将代碼片轉換為對象的方法

對于lambda表達式中的多個參數,如果需要顯示聲明一個參數的類型,那麼必須為所有的參數聲明類型

Lambda體隻包含單個表達式,被稱為表達式體,有時也被稱為表達式lambda。由代碼塊構成的被稱為塊lambda

塊lambda必須顯示使用return語句來傳回值

Lambda體本質上與方法體類似。

Lambda表達式自身不能指定類型參數,是以lambda表達式不能是泛型。(然而,由于存在類型推斷,所有lambda表達式都展現出一些類似與泛型的特征),與lambda表達式關聯的函數式接口可以是泛型

Lambda表達式可以使用或修改其調用類的執行個體變量,隻是不能使用其外層作用域内的具備變量,除非該變量實質上是final變量

方法引用提供了一種引用而不執行方法的方式

靜态方法的方法引用

ClassName::methodName

執行個體方法的方法引用

泛型中的方法引用

構造函數引用

classname::new

要為數組建立構造函數引用 type[]::new

在很多時候,并不需要自己定義函數式接口,因為JDK8中包含了新包java.util.function,其中提供了一些預定義的函數式接口

并發實用工具

原始的多線程支援并沒有提供一些進階特性,比如信号量、線程池以及執行管理器,這些特性有助于建立強大的并發程式

并發程式是指廣泛而完整地執行多個并發線程的程式

JDK5增加了并發實用工具,通常也被稱為并發API。例如同步器(比如信号量)、線程池、執行管理器、鎖、一些并發集合以及使用線程擷取計算結果的流線化方式

JDK7對之進行了極大擴充。最重要的新增内容是Fork/Join架構。Fork/Join架構使得建立使用多個處理器的程式更加容易,因而簡化了兩個或多個片真正同時執行,而不僅僅是時間切片這類程式的建立

因為多核系統的不斷普及,涉及Fork/Join架構的解決方案變得更加普遍

同步器、執行器、并發集合、Fork/Join架構

同步器提供了同步多線程間互動的進階方法

執行器管理線程的執行,執行器層次的頂部是Executor接口,該接口用于啟動線程。ExecutorService擴充了Executor,并提供了管理執行的方法。與執行器相關的是Future和Callable接口

并發集合類:ConcurrentHashMap、ConcurrentLinkedQueue和CopyOnWriteArrayList

Fork/Join架構支援并行程式設計,包含的類有ForkJoinTask、ForkJoinPool、RecursiveTask以及RecursiveAction

Semaphore實作率經典的信号量。信号量通過計數器控制對共享資源的通路

CountDownLatch在初始建立時帶有事件數量計數器,在釋放鎖存器之前,必須發生指定數量的事件

CyclicBarrier,直到指定數量的線程都到達界限點為止,才開始執行

Exchanger設計目的是簡化兩個線程之間的資料交換

Phaser該類的主要目的是允許表示一個或多個活動階段的線程進行同步

使用執行器,用于啟動并控制線程的執行,核心是Executor接口,定義的方法

void execute(Runnable thead)

ExecutorService接口通過添加用于幫助管理和控制線程執行的方法,對Executor接口進行了擴充

執行器還定義了ScheduledExecutorService接口,擴充了ExecutorService以支援線程排程

3個執行器類:ThreadPoolExecutor、ScheduledThreadPoolExecutor以及ForkJoinPool

盡管可以直接使用ThreadPoolExecutor和ScheduledThreadPoolExecutor,但是絕大數情況下,會希望調用Executors實用工具類定義的靜态工廠方法來回去執行器

Callable泛型接口表示傳回值的線程

Future泛型接口表示将由Callable對象傳回的值

當多個線程需要通路共享資料時,鎖特别有用,鎖是一些對象,它們為使用Synchronized提供了替代技術,工作原理:在通路共享資源之前,申請用于保護資源的鎖;當資源通路完成時,釋放鎖。當某個線程正在使用鎖時,如果另一個線程嘗試申請鎖,那麼後者會被挂起,

原子操作

通過Fork/Join架構進行并行程式設計

JDK7增加了一些支援并行程式設計的類和接口。它們通常被稱作Fork/Join架構,通過兩種方式增強多線程程式設計,首先簡化了多線程建立和使用,其次Fork/Join架構自動使用多處理器

通過Fork/Join架構,應用程式能夠自動伸縮,以利用可用數量的處理器

傳統多線程與并行程式設計之間的差別:在單核cpu系統中,多線程程式設計用于允許兩個或多個任務共享cpu,沒有對可以使用兩個或更多個cpu的情況進行優化

并行程式設計能夠顯著提高程式的性能

主要的Fork/Join類: ForkJoinTask、ForkJoinPool、RecursiveAction、RecusiveTask

ForkJoinPool使用一種稱為工作挪用(Work stealing)的方式來管理線程的執行

ForkJoinPool使用守護線程。

分而治之的政策,作為通用規則,使用Fork/Join架構會用到基于遞歸的粉兒治之的政策。

政策:将任務遞歸的劃分成為更小的子任務,直到子任務足夠小,進而能夠被連續的處理為止。直到達到臨界點為止,在該臨界點,連續的解決方案比進行另一次劃分更快

分而治之政策的優勢在于處理過程可以并行發生。通常最佳臨界點是通過配置執行特征獲得的,最好避免使用過大或過小的臨界點。根據經驗任務應當在100到10000個計算步驟之間的某個位置執行

對于将在已知系統中運作的應用程式來說,處理器的數量已知,是以可以使用處理器的數量來決定臨界點的選取

JDK8存在ForkJoinPool公共池

提高處理速度可以在計算機上試驗不同的臨界點和運作級别

為了更好地利用Fork/Join架構,任務應當執行計算,這些計算在沒有外部阻塞或同步時就能運作。

不要對代碼将在其中運作的環境做出假設(不應當假定可用處理器的某個特定數量、不受外部程序的影響),Fork/Join架構為将并行程式設計技術內建到更複雜的應用程式中提供了不錯的方式

喜歡 (0)or分享 (0)