超越線程池:Java并發(fā)并沒(méi)有你想的那么糟糕
很多人一直嘮叨著并發(fā)中的新概念。然而,許多開(kāi)發(fā)人員還沒(méi)有機(jī)會(huì)把過(guò)多的注意力都放在上面。在這篇文章中,我們將帶您了解Java 8 streams、 Hadoop、 Apache Spark、 Quasar fibers以及響應(yīng)式編程,讓你迅速入門(mén)。尤其是如果你不經(jīng)常用它們的話。一句話,它并不遙遠(yuǎn),它就在我們身邊。
我們?cè)撛趺醋?
談到并發(fā),一種很好的方式來(lái)形容當(dāng)前的問(wèn)題是來(lái)回答幾個(gè)小問(wèn)題以便更好的了解它:
它是一個(gè)數(shù)據(jù)處理任務(wù)么?如果是這樣的話,它可以分解為獨(dú)立的任務(wù)單元么?
操作系統(tǒng)、虛擬機(jī)和你的代碼之間的關(guān)系是什么?(本地線程 VS 輕量級(jí)線程)
有多少機(jī)器和處理器參與?(單核 VS 多核)
讓我們帶著問(wèn)題,一起找出每個(gè)問(wèn)題的最佳答案吧。
1、從線程池到并行流
在Java 8中,我們了解到新的流API接口,它允許應(yīng)用聚集操作,如篩選、排序或者映射數(shù)據(jù)流。流允許我們做的另一件事情是,在多核機(jī)器上應(yīng)用并行操作。并行流 ——通過(guò)把Fork/Join框架引入Java 7將線程間的工作分離。Java 6并發(fā)庫(kù),我們看到了ExecutorService創(chuàng)建和處理我們的工作線程池,這不得不說(shuō)是個(gè)進(jìn)步。
Fork/Join也建立在ExecutorService之上,與傳統(tǒng)的線程主要的區(qū)別在于如何在線程和支持多核的機(jī)器間分配工作。用一個(gè)簡(jiǎn)單的 ExecutorService你能完全控制工作線程之間的負(fù)載分布,確立每個(gè)任務(wù)的大小以便線程來(lái)處理。而Fork/Join,恰好有個(gè)work-stealing算法分配線程間的負(fù)載。簡(jiǎn)而言之,這允許大型任務(wù)可以被分成更小單元,并在不同的線程間處理,最終我們可以知道——它是為了平衡線程間的 工作。然而,這并不是萬(wàn)能的。
有時(shí)并行流會(huì)減慢你速度的,所以你需要多想想。在你的方法中使用parallelStream會(huì)導(dǎo)致瓶頸和減速(在我們基準(zhǔn)測(cè)試中跑慢了約15%左右)。假設(shè)我們已經(jīng)運(yùn)行多個(gè)線程,在其中一些我們使用parallelStream,在線程池中添加越來(lái)越多的線程。這可以很容易超過(guò)我們的核心處理能力,由于增加了上下文轉(zhuǎn)換一切都慢下來(lái)了。
小結(jié):在單機(jī)上并行流使線程處理抽象化,在一定程度上這會(huì)均衡核心間的負(fù)載。然而,如果你想高效使用它們,記住硬件是關(guān)鍵而不是生產(chǎn)更多的線程而超出機(jī)器的處理能力。
2、Apache Hadoop和Apache Spark
接下來(lái)談多核機(jī)器、 PB級(jí)數(shù)據(jù)和任務(wù),這跟所有從twitter提到的Java或重載機(jī)器學(xué)習(xí)算法類(lèi)似。談到Hadoop,不得不說(shuō)這個(gè)應(yīng)用廣泛的框架及它的組 件:Hadoop分布式文件系統(tǒng)(HDFS)、資源管理平臺(tái)(YARN)、數(shù)據(jù)處理模塊(MapReduce)和其他所需的類(lèi)庫(kù)和工具(Common)。 在這些組件上層還有一些其他很受歡迎的可選工具,比如運(yùn)行在HDFS上的數(shù)據(jù)庫(kù)(HBase)、查詢(xún)語(yǔ)言平臺(tái)(Pig)和數(shù)據(jù)倉(cāng)庫(kù)基礎(chǔ)結(jié)構(gòu)(Hive)。
Apache Spark 作為一種新數(shù)據(jù)處理模塊,以?xún)?nèi)存性能和快速執(zhí)行的彈性分布式數(shù)據(jù)集(RDDs)而出名,不同于不能高效使用內(nèi)存和磁盤(pán)的Hadoop MapReduce。Databricks公布的最新標(biāo)準(zhǔn)顯示當(dāng)用少于10倍節(jié)點(diǎn)的時(shí)候,對(duì)1PB數(shù)據(jù)的排序Spark比Hadoop快三倍。
典型的Hadoop用例在于查詢(xún)數(shù)據(jù),而Spark正以其快速的機(jī)器學(xué)習(xí)算法越來(lái)越出名。但這只是冰山一角,Databricks如是說(shuō):“Spark 使應(yīng)用程序在Hadoop集群中運(yùn)行在內(nèi)存中快100倍,當(dāng)運(yùn)行在磁盤(pán)中時(shí)甚至快10倍”。
小結(jié):Spark是在Hadoop生態(tài)系統(tǒng)中的后起之秀,有一個(gè)常見(jiàn)的誤解是我們現(xiàn)在經(jīng)常談它一些不合作或競(jìng)爭(zhēng)的事情,但是我認(rèn)為我們?cè)谶@正在看到這個(gè)框架的發(fā)展。
3、Quasar fibers
我們有機(jī)會(huì)運(yùn)行在Hadoop,現(xiàn)在讓我們回到單機(jī)。事實(shí)上,在Java多線程應(yīng)用程序和集中在單線程上,讓我們眼光再長(zhǎng)遠(yuǎn)些。就我們而言,HotSpot JVM線程與本地系統(tǒng)線程相同,持有一個(gè)線程并且運(yùn)行在”虛擬“線程中,這在fibers中都包含的。Java沒(méi)有原生的fibers支持,但是不要擔(dān) 心,Quasar通過(guò)Parallel Universe解決了我們的問(wèn)題。
Quasar 是一個(gè)開(kāi)源的JVM庫(kù)。它支持fibers(也稱(chēng)為輕量級(jí)線程),并且還充當(dāng)框架的角色,在后面中我會(huì)提到。在這上下文轉(zhuǎn)換是它本質(zhì)的名字。當(dāng)我們核心數(shù) 量有限,一旦本地線程數(shù)量越大我們就會(huì)收到越來(lái)越多的上下文開(kāi)銷(xiāo)。一種解決這個(gè)問(wèn)題的方式是fibers,使用單線程支持”多線程“。這看起來(lái)像threadcepiton的一個(gè)實(shí)例。
Fibers還可以被視為一個(gè)從線程池的進(jìn)化,當(dāng)我們通過(guò)應(yīng)用并行流的時(shí)候避開(kāi)了線程過(guò)載的危險(xiǎn)。他們更容易衡量線程和允許令人可觀的并行”輕量“線程數(shù)量。它們不是為了取代線程,而是應(yīng)該用在那些相對(duì)來(lái)說(shuō)經(jīng)常堵塞的代碼中,就如同擔(dān)任真正異步線程的角色。
小結(jié):并行領(lǐng)域在Java并發(fā)性中正提供一種新的思路,雖然還沒(méi)有版本發(fā)布,但是值得一試。
4、Actor和響應(yīng)式編程
在響應(yīng)式的官方言論中,最新的釋義有4原則:響應(yīng)、有彈性、靈活性和消息驅(qū)動(dòng)。這基本意味著快速、容錯(cuò)、可伸縮的和支持非阻塞通信。
讓我們看看Akka Actor是如果支持它的吧。簡(jiǎn)單來(lái)講Actor有一個(gè)狀態(tài)和一個(gè)特定的行為,通過(guò)交換消息溝通彼此的郵箱。一個(gè)Actor系統(tǒng)作為一個(gè)整體應(yīng)該被每個(gè)應(yīng) 用程序創(chuàng)建,擁有一個(gè)層次結(jié)構(gòu)將任務(wù)分解成更小的任務(wù)以便每個(gè)角色最多只有一個(gè)監(jiān)督的角色。一個(gè)角色也可以處理這個(gè)任務(wù),通過(guò)委托給另一個(gè)角色將其進(jìn)一步 分解或在實(shí)例失敗的情況下,將它反饋給它的監(jiān)督者。無(wú)論哪種方式,消息不應(yīng)該包括行為或者共享可變的狀態(tài),每個(gè)角色都有一個(gè)獨(dú)立的狀態(tài)和行為。
它是一個(gè)從大多數(shù)開(kāi)發(fā)者在使用的并發(fā)模型的思考模式的轉(zhuǎn)移。盡管它起源于70年代,但是為了適應(yīng)現(xiàn)代應(yīng)用程序的要求,直到最近幾年它才復(fù)蘇。并行領(lǐng)域的Quasar也支持Actor,實(shí)現(xiàn)的主要區(qū)別在于fibers/輕量級(jí)線程。
小結(jié):相反的,Actor模型需要管理線程池,讓它遠(yuǎn)離使用工具包。今天面對(duì)這種應(yīng)用程序處理的問(wèn)題,尤其在我們可以處理?yè)碛懈嗪诵牡母卟l(fā)系統(tǒng)方面又重新有了關(guān)注。
總結(jié)
關(guān)于使用并發(fā)或者并行算法,我們今天通過(guò)介紹4種方法來(lái)解決問(wèn)題來(lái)應(yīng)對(duì)你需要的場(chǎng)景。希望這有 助于激起你的興趣,以及在這大談并發(fā)話題的現(xiàn)在開(kāi)拓下你的視野。超越線程池,有一種將這委托給語(yǔ)言及它的工具的趨勢(shì)——關(guān)注新的技術(shù)并應(yīng)用它而不是花費(fèi)無(wú) 數(shù)個(gè)小時(shí)解決競(jìng)態(tài)條件和鎖。