Devoxx 2012:Java 8 Lambda和并行性,第1部分
總覽
Devoxx是世界上最大的獨立于供應商的Java會議,于11月12日至16日在比利時的Atwerp舉行。 今年規(guī)模更大了,來自40個不同國家的3400名與會者。 和去年一樣 ,我和來自SAP的一小群同事都來了,并享受了很多。
在Nao機器人令人印象深刻的舞蹈和開幕主題演講之后,超過200場會議探討了從Java SE到方法論和機器人技術的各種不同技術領域。 對我而言,最有趣的主題之一是JDK 8中Java語言和平臺的演變。
我之所以感興趣,部分原因是我已經開始在Wordcounter上工作,并在另一個并發(fā)的Java庫Evictor上完成工作,我將在以后的博客中發(fā)表有關該庫的博客。 在本博客系列中,我想分享一些我參加過的有關此主題的會議的更詳細的摘要。 這三個會話都在同一天,同一房間,一個接一個的空間中進行,共同為Java 8中的lambda,并行集合和并行性提供了三種不同的觀點。
- 在通往JDK 8的路上:Lambda,并行庫等,作者Joe Darcy
- 封閉與收藏–莫里斯·納夫塔林(Maurice Naftalin)的《八點后的世界》
- Fork / Join,lambda和parallel(): Jose Paumard簡化了并行計算(太容易了)
在這篇文章中,我將介紹第一屆會議,其他兩屆會議即將舉行。
通往JDK 8的道路上:Lambda,并行庫等
在第一屆會議上,Oracle多個項目的首席工程師Joe Darcy介紹了JDK 8中所用語言的關鍵更改,例如lambda表達式和默認方法,總結了實現(xiàn)方法,并研究了并行庫及其新特性。編程模型。 本次會議的幻燈片可在此處獲得 。
不斷發(fā)展的Java平臺
喬首先談到了上下文和與語言發(fā)展有關的關注。
OpenJDK的一般演變策略是:
- 不要破壞二進制兼容性
- 避免引入源不兼容性。
- 管理行為兼容性更改
上面的列表還擴展到語言的發(fā)展。 這些規(guī)則意味著將始終識別舊的類文件,限制當前合法代碼停止編譯的情況,并且還避免了生成的代碼中引入行為更改的更改。 該策略的目標是保持現(xiàn)有二進制文件的鏈接和運行,并保持現(xiàn)有源代碼的編譯。
這也影響了選擇要在語言本身中實現(xiàn)的功能集以及它們的實現(xiàn)方式。 在向Java添加閉包時,此類擔憂也有效。 例如,接口是一把雙刃劍。 利用我們今天擁有的語言功能,它們無法隨著時間的推移而兼容發(fā)展。 但是,在現(xiàn)實中,隨著人們對API的期望的提高,API逐漸發(fā)展。 在語言中添加閉包會導致一個完全不同的編程模型,這意味著如果可以兼容地擴展接口,那將非常有幫助。 這導致更改同時影響語言和VM,稱為default methods 。
Lambda項目
Lambda項目引入了協(xié)調的語言,庫和VM更改。 在該語言中,有l(wèi)ambda expressions和默認方法。 在庫中,有bulk operations on collections以及對并行性的附加支持。 在虛擬機中,除默認方法外,還對invokedynamic功能進行了增強。 這是對語言所做的最大更改,比泛型等其他重大更改要大。
什么是lambda表達式?
lambda expression是一種匿名方法,具有一個參數(shù)列表,一個返回類型和一個主體,并且能夠從封閉范圍引用值:
(Object o) -> o.toString() (Person p) -> p.getName().equals(name)除了lambda表達式外,還有method reference語法:
Object::toString()lambda的主要好處是它允許程序員將代碼視為數(shù)據,將其存儲在變量中并將其傳遞給方法。
一些歷史
在1995年首次引入Java時,沒有多少種語言具有閉包功能,但如今,幾乎所有主流語言都使用閉包語言,甚至C ++也是如此。 對于Java來說,獲得關閉支持一直是一條漫長而曲折的道路,直到Lambda項目最終于2009年12月開始。目前的狀態(tài)是JSR 335處于早期草稿審查中 ,有可用的二進制版本 ,并且有望成為很快,JDK 8主線的一部分就會構建。
內部和外部迭代
有兩種執(zhí)行迭代的方法–內部和外部。 在external iteration您將數(shù)據帶入代碼,而在internal iteration您將代碼帶入數(shù)據。 外部迭代就是我們今天所擁有的,例如:
for (Shape s : shapes) {if (s.getColor() == RED)s.setColor(BLUE); }這種方法有幾個局限性。 其中之一是上述循環(huán)inherently sequential上是inherently sequential ,即使沒有根本原因不能由多個線程執(zhí)行,也是如此。
重新編寫以對lambda使用內部迭代,上面的代碼將是:
shapes.forEach(s -> {if (s.getColor() == RED)s.setColor(BLUE); })這不僅是語法上的更改,因為現(xiàn)在該庫可以控制迭代的發(fā)生方式。 以這種方式編寫的代碼表達的內容更多what而更少, how ,如何留給庫。 庫作者可以自由使用并行性,亂序執(zhí)行,懶惰和所有其他技術。 這允許庫對行為進行抽象,這從根本上是一種更強大的處理方式。
功能介面
Lambda項目避免了添加新類型,而是重用了現(xiàn)有的編碼實踐。 Java程序員熟悉并長期使用一種方法(如Runnable , Comparator或ActionListener使用接口。 這些接口現(xiàn)在稱為functional interfaces 。 還將有新的功能接口,例如Predicate 和Block 。 Lambda表達式求值為功能接口的實例,例如:
PredicateisEmpty = s -> s.isEmpty(); Predicate isEmpty = String::isEmpty; Runnable r = () -> { System.out.println(“Boo!”) };因此,現(xiàn)有庫與lambda向前兼容,從而導致“自動升級”,從而保持了對這些庫的大量投資。
默認方法
上面的示例在Collection上使用了新方法forEach 。 但是,將方法添加到現(xiàn)有接口在Java中是不行的,因為當客戶端在未實現(xiàn)該方法的舊類上調用新方法時,它將導致運行時異常。
default method是具有實現(xiàn)的接口方法,該實現(xiàn)由VM在鏈接時編織。 從某種意義上說,這是multiple inheritance ,但是沒有理由驚慌,因為這是behavior多重繼承,而不是狀態(tài)的多重繼承。 語法如下所示:
interface Collection<T> {...default void forEach(Block<T> action) {for (T t : this)action.apply(t);} }有某些inheritance rules可以解決多個超類型之間的沖突:
- 規(guī)則1 –首選超類方法而不是接口方法(“類獲勝”)
- 規(guī)則2 –傾向于使用更具體的接口,而不是更少的接口(“子類型獲勝”)
- 規(guī)則3 –否則,就好像該方法是抽象方法一樣。 在默認值沖突的情況下,具體類必須提供一個實現(xiàn)。
總之,通過尋找unique , most specific default-providing interface來解決沖突。 有了這些規(guī)則,“鉆石”就不成問題了。 在最壞的情況下,如果沒有唯一,最具體的方法實現(xiàn),則子類必須提供一個方法,否則會出現(xiàn)編譯器錯誤。 如果此實現(xiàn)需要調用繼承的實現(xiàn)之一,則此新語法為A.super.m() 。
默認方法的主要目標是API演變,但它們本身也可用作繼承機制。 從中受益的另一種方法是optional methods 。 例如,大多數(shù)Iterator實現(xiàn)都沒有提供有用的remove() ,因此可以將其聲明為“可選”,如下所示:
interface Iterator<T> {...default void remove() {throw new UnsupportedOperationException();} }對集合進行批量操作
對集合執(zhí)行批量操作還可以實現(xiàn)映射/簡化編程風格。 例如,可以通過從shapes集合中獲取stream ,過濾紅色元素然后僅對過濾后的元素進行迭代來進一步分解以上代碼:
shapes.stream().filter(s -> s.getColor() == RED).forEach(s -> { s.setColor(BLUE); });上面的代碼與您實際想要完成的問題的陳述更為接近。 還有其他有用的批量操作,例如map , into或sum 。 該編程模型的主要優(yōu)點是:
- 更具可組合性
- 清晰–每個階段都做一件事
- 該庫可以使用并行性,亂序,惰性來提高性能等。
stream是添加到平臺的基本的新抽象。 它封裝了laziness ,以更好地替代諸如LazyList類的“惰性”集合。 它是一種允許從其中獲取元素序列的工具,其源是集合,數(shù)組或函數(shù)。 具有流的基本編程模型是管道的模型,例如collection-filter-map-sum或array-map-sorted-forEach 。 由于流是惰性的,因此它們僅根據需要的元素進行計算,這在filter-map-findFirst類的情況下會filter-map-findFirst 。
流的另一個優(yōu)點是,通過讓庫在后臺使用fork / join來簡化編程并避免樣板,它們允許利用fork / join并行性。
實施技術
在演講的最后一部分,喬描述了可能的lambda表達式實現(xiàn)技術的優(yōu)缺點。 考慮了不同的選項,例如內部類和方法句柄,但由于它們的缺點而未被接受。 最好的解決方案是添加一個間接級別,方法是讓編譯器發(fā)出聲明性配方(而不是命令性代碼)以創(chuàng)建lambda,然后讓運行時以它認為合適的方式執(zhí)行該配方(并確保它是快速的)。
這聽起來像是invokedynamic的工作,它是Java SE 7引入的一種全新的調用模式,其原因完全不同-支持JVM上的動態(tài)語言。 事實證明,此功能不再僅適用于動態(tài)語言,因為它為lambda提供了合適的實現(xiàn)機制,并且在性能方面也要好得多。
結論
Lambda項目是跨Java語言和平臺的大型協(xié)調更新。 它為集合提供了更強大的編程模型,并利用了VM中的新功能。 您可以通過下載具有l(wèi)ambda支持的JDK8構建來評估這些新功能。 具有Lambda支持的NetBeans構建和具有Lambda支持的 IntelliJ IDEA 12 EAP構建中也已經提供了IDE 支持 。
我已經在Wordcounter中使用Java中的lambda進行了自己的體驗。 正如我已經寫過的,我堅信這種編程風格將很快在Java中普及,因此,如果您還沒有使用它的經驗,我鼓勵您嘗試一下。
參考: Devoxx 2012:Java 8 Lambda和Parallelism,第1部分,來自我們的JCG合作伙伴 Stoyan Rachev,位于Stoyan Rachev的Blog博客上。
翻譯自: https://www.javacodegeeks.com/2012/12/devoxx-2012-java-8-lambda-and-parallelism-part-1.html
總結
以上是生活随笔為你收集整理的Devoxx 2012:Java 8 Lambda和并行性,第1部分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 真我GT5今日10点正式开售!2999元
- 下一篇: 使用JSF 2.0可以更轻松地进行多字段