John Jiang

          a cup of Java, cheers!
          https://github.com/johnshajiang/blog

             :: 首頁 ::  :: 聯(lián)系 :: 聚合  :: 管理 ::
            131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
          Java Concurrent Animated
              在最新一期的Java Magazine中有一篇訪談,介紹了一個學習Java并發(fā)編程的動畫應用Java Concurrent Animated。該應用以十分直觀的方式展示了Java并發(fā)工具包中的每一個重要組件,降低了學習Java并發(fā)編程的難度。(2013.12.07最后更新)

          Java Magazine:有多少人已經試用過了你的Java Concurrent Animated應用?
          Grazi:該應用是在2009年7月被引入的,從那時算起,已經有了大約20000的下載量。但考慮到已有約一千萬的Java開發(fā)者,這個下載量才只是開始。按國家區(qū)分,下載最多的分別是美國(23%),印度(14)和中國(7%)。
              你可以下載一個可以執(zhí)行的JAR文件,然后僅需雙擊它就可以運行了。該應用是由菜單驅動的,或者也可以使用向上或向下鍵在不同的圖像和動畫之間進行導航。它能運行在諸如Windows,Mac,Linux等等所有的平臺上。它要求安裝Java SE 6或更高的版本。

          Java Magazine:對這個應用最典型的反饋是什么?
          Grazi:大家告訴我這個工具很好用。許多人確實對此感到興奮,尤其是那些正試圖向團隊教授合適并發(fā)技術的老師與領導們。Java是最早在核心類庫中引入并發(fā)的語言之一。在當時,這是一個很強大的特性,但我們很快就發(fā)現(xiàn)一個非常優(yōu)秀的程序員與會寫出很糟糕的并發(fā)代碼。進行恰當?shù)牟l(fā)編程是一件困難甚至是不可能的事情,但是如何人們能花些時間去理解一些現(xiàn)有的框架,那么在進行并發(fā)編碼時所產生潛在錯誤就會變得極少。
              例如,去看看Java內存模型。開發(fā)者經常忽視Java內存模型,而像個幸福的傻瓜一樣在編碼,那么他們的程序會不太正常,因為Java虛擬機(JVM)和服務器可能無法利用到由Java內存模型所提供的優(yōu)化。由于內核在速度與數(shù)量上都有了增長,廠商們期望能夠高效地利用到這些內核,然而由于錯誤的并發(fā)管理,本來如期運行的程序卻開始遇到了一些零星的錯誤。

          Java Magazine:你是說,這個應用會以我們所虛構的方式去使開發(fā)者們能夠更快且直觀地掌握Java并發(fā)的原理與實踐?
          Grazi:那是達到這一目的一個有趣的途徑。你知道的,Java Concurrent Animated并不是一個Flash動畫。它是一組可交互的Java程序,也即,每個動畫都是真地在使用它所要演示的并發(fā)組件。在屏幕的右邊是一個展示代碼片斷的面板,由于動畫的運行,它會動態(tài)地高亮顯示及恢復正在執(zhí)行的代碼。
              讓你給你一個例子,這個例子發(fā)生在ReadWriteLock這個動畫中。ReadWriteLock用于確保數(shù)據(jù)的一致性。它允許不受數(shù)量限制的線程去獲取讀鎖,并能并發(fā)地對這個鎖進行操作。但是,寫線程在獲取這個鎖之前只能等待所有的讀線程執(zhí)行結束。一旦一個寫線程獲得了這個鎖,那么其它的讀線程或寫線程將無法獲取它。
              假設一個寫線程正在等待正在執(zhí)行中的讀線程去釋放這個讀鎖,但突然一個新的讀線程跑過來了。那么誰應該獲得這個鎖會比較好呢?這個新的讀線程應該跑到寫線程前面去嗎?畢竟,如果其它的讀線程已經獲得了這個鎖,那么新來的讀線程為什么要去等一個尚在等待中的寫線程呢?而這實際上這正是Java 5所干的事兒。但某次我在Java 6上運行這個動畫時,我注意到行為發(fā)生了改變。即,隨后而來的讀線程在獲取到這個鎖之前可能要等待所有的寫線程先釋放鎖。
              我認為這個新的行為是一個BUG,且向并發(fā)專家Heinz Kabutz博士提及了此事。博士解釋道,這不是一個錯誤,而一個特性。如果允許新到的讀線程跳到正處于等待中的寫線程的前面去,這就存在產生線程饑餓條件的高風險。因為,存在一種很大的可能性,可能沒有任何寫線程能獲得這個鎖,它們將永遠等待著。這就是一個如何使用動畫去警示依賴于JVM運行時版本的線程行為的例子。

          Java Magazine:以動畫教程的形式來展示特殊值,在Java并發(fā)編程中有何與眾不同嗎?
          Grazi:Miller定律教會我們,我們的大腦在某一時刻能處理的思維的數(shù)量是有限的。人類大腦傾向于進行順序的思維處理,那么即便我們能夠克服身體上的束縛,并能夠去正確地進行理解,在以后也很難返回至前去重新構造前面的思維處理。可以肯定地是,如果另一個開發(fā)者在以后能深入對其進行研究,那么仍然非常難以從原有的思維成果中再次捕捉到認知軌跡。這樣的話,脆弱的代碼就會很突然地不能正常工作了。
              通過使用框架,我們不僅將并發(fā)編程委托給了創(chuàng)建和維護該框架的聰明開發(fā)者們,而且還為溝通設計時引入了一個詞典。所以,我可以說,“下面的代碼會當作CyclicBarrier去執(zhí)行”,而人們會明白那是什么意思。通過為java.util.concurrent中的所有組件都引入一個可交互化的動畫應用,開發(fā)者們點著鼠標就能很方便地將他們所探究的功能進行可視化,使理解這些算法變得真心簡單了。

          Java Magazine:你當時正在研究某些直覺,這些直覺可以幫助更方便地學習并發(fā)編程。從開發(fā)者的反饋來看,這些直覺看起來是有效的。
          Grazi:是的。例如,我前面解釋的ReadWriteLock基本功能。讀者們可能理解了,也可能沒有。現(xiàn)在讓我們看看這個與其有關的動畫,如圖表1所示。

              綠色線程是讀線程,最上面的白色線程(帶著菱形箭頭)是一個寫線程,它下面的白色線程是一個新的讀線程,該線程在獲取鎖之前必須要等待所有的讀線程與寫線程執(zhí)行完畢。如果你點擊按鈕并觀看這些動畫,會比通過瀏覽繁冗的解釋性文字去進行理解要簡單得多了。

          Java Magazine:Heinz Kabutz評論道,Java被構建成能夠一次性做許多事情,而這正與并發(fā)完全相關。你的學習系統(tǒng)是如何提高程序員的技能,以便他們能降低并發(fā)錯誤的風險。
          Grazi:經常地,當我要努力克服一個并發(fā)問題時,我知道解決方案就存在于某個設計模式中,但是哪一個呢?在開發(fā)者探尋一個正確解決方案時,Java Concurrent Animated為他們提供了一個所有方案的目錄;在激發(fā)出正確方案的過程中,它扮演著向導的角色。

          Java Magazine:當你管理的團隊正在使用Java并發(fā),并且你和你的團隊都想更好地去理解Java并發(fā),Java Concurrent Animated有著它的出發(fā)點。是什么導致你使用動畫呢,能描述下這個過程嗎?
          Grazi:我的培訓是針對投資部門的服務器端Java應用,在那里,并發(fā)是一個通常都會受到關注的問題。交易員們要求延遲要低,這樣可以確保他們在這個需要于一毫秒窗口時間內捕捉交易機會的比賽中不會成為失敗者。批量處理也要求快速完成,等等。所以我開始看到那些可怕的只寫(write-only)組件,這些組件使人們在并發(fā)編程掙扎著。我自己也身處其中。
              某天下午,我正坐在機場內,將要前往芝加哥為我的團隊做一個關于并發(fā)的講演。我正對講演的PPT進行最后的處理,那組幻燈片著重演示了每一個重要的組件。為了引導我瀏覽java.util.concurrent中每個并發(fā)組件的狀態(tài),我寫了一些狀態(tài)機,它們展示了一些供我參考用的簡單文本消息。在之前的生涯中,我曾在一家互聯(lián)網創(chuàng)業(yè)公司中開發(fā)交互式的游戲,所以我懂得許多與動畫相關的知識。這使我想到可以將PPT替換成一組交互式的動畫應用,那會更為直觀。
              在等飛機的過程中,我寫了一個初步的動畫引擎,然后在我的狀態(tài)機中調用了這個引擎。到了第二天早晨,我已經有一個可用的原型程序。多年來,我一直致力于這個框架,并且吸引了其他專家的建議。我傳遞過一份早期版本給Brian Goetz,令人驚訝的是,他為每個動畫程序都給出了建議。我將他的所有建議到吸收到了該框架中。在我的第一次JavaOne講演中,Kirk Pepperdine加入了進來。他建議為動畫應用在真正的PPT中加入描述,以便講演者能記住正在討論的內容。隨后我加上那些描述,這確實非常有用--不只是對講演者有用,對于終端用戶也很有用。Heinz Kabutz也加入了那場講演,并建議修改某些動畫,以使它們更為直觀。
              在另一場講演中,一個很有激情的軟件咨詢師Oliver Zeigermann指出,很顯然缺少了針對ConcurrentHashMap的動畫。我問他是否有興趣貢獻這個動畫,隨后他添加了那個很有價值的動畫程序。

          Java Magazine:你能帶著我們過一遍Java并發(fā)工具包中的類嗎?并能否解釋一下這些動畫程序是如何使開發(fā)者們更易于深入理解這些類?
          Grazi:好的,但在沒有動畫程序的情況下確實很難辦到。讓我們看看CyclicBarrier,它有兩個重要的狀態(tài),如圖2和圖3所示,它們展示了一個障礙和四個成員。在圖2中,我們可以看到有三個成員已經到了,所以它們被阻止繼續(xù)前進。圖3展示了,一旦第四個成員也到達了,每個成員又可以向前走了。



              這就形象地詮釋了障礙的概念,亦即,在所有成員到達障礙點之前,每個成員必須等待。隨著并發(fā)組件復雜度的增加--例如Fork/Join的動畫,以及那些演示原生的wait和notify機制的動畫--使用動畫程序的好處就更不肖說了。

          Java Magazine:談談在創(chuàng)建這些動畫程序的過程中所遇到的一些挑戰(zhàn)。
          Grazi:有一些挑戰(zhàn)。開始時,線程被表示成箭頭。對于多數(shù)并發(fā)組件,這種表示法是有效的。后來我們必須提供一個可視化方案,不僅要表示線程,還要表示BlockingQueue中的對象。所以,我不得不引入一個稱之為"精靈類型(sprite-type)"的概念,然后我們有了一個箭頭型的精靈類型和一個新的"對象"型的精靈類型。后來,ConcurrentHashMap和AtomicInteger又需要新的精靈類型,因為我們試圖要對他們的計算與交換行為進行可視化。
              后面又來了Fork/Join,新的挑戰(zhàn)就是如何去表現(xiàn)那些完全不同于現(xiàn)有框架所表現(xiàn)的可視化部件。還有一個挑戰(zhàn),即Fork/Join動畫需要解決一個實際的問題,但這個動畫應該解決一個什么樣的問題呢?
              開始時,我讓這個動畫程序去求Fibonacci數(shù)列,但卻行不通。我在這個問題上糾結了兩天時間,直到我認識到Fibonacci數(shù)列(Fn+1=Fn+Fn-1)無法高效地并行化,因為每個值都依賴于它前面的值。所以,無論你如何試圖對其實施并行化,它天生就是一個順序化的計算。所以我換成了另一個問題--查找數(shù)組中的最大元素,這樣就好了。在這個動畫中,你可以很精確地看到如何使用一個隨機的數(shù)列去解決這個問題(如圖4所示)。


          Java Magazine:你都在哪里講演過這些動畫程序?
          Grazi:在JavaOne中講演過幾次,在其它的許多會議,如奧斯陸中的JavaZone,蘇黎世的Jazoon,紐約的QCon,以及許多SIG(特別興趣組)和JUG(Java用戶組)中也都講演過。我喜歡講演,我也喜歡周游世界,而Java Concurrent Animated為我提供了一個極好的機會去做這兩件事情。它總能獲得極高的評價。
              Java Concurrent Animated的講演提供了一種意識,并且它們也向出席的開發(fā)者們展示了下載這一框架的價值,而且它還展示了,如果你擁有了框架和靈感啟迪,學習并發(fā)編程會是多么的容易。
          posted on 2013-12-07 17:45 John Jiang 閱讀(2415) 評論(1)  編輯  收藏 所屬分類: JavaSEJavaConcurrency翻譯

          評論

          # re: Java Concurrent Animated(譯) 2013-12-14 23:55 左岸
          說實話還真沒有了解的這么深過 學習了  回復  更多評論
            

          主站蜘蛛池模板: 宁晋县| 宝应县| 雷山县| 清镇市| 获嘉县| 汕头市| 都江堰市| 沈丘县| 遂平县| 涟源市| 西昌市| 辽阳县| 北辰区| 昔阳县| 章丘市| 微山县| 夏津县| 苍山县| 磐石市| 育儿| 绿春县| 南溪县| 德兴市| 宁化县| 调兵山市| 隆林| 汉阴县| 和平县| 黑龙江省| 蒙自县| 武强县| 韶山市| 江华| 蒙城县| 贵定县| 陇川县| 大安市| 新丰县| 临朐县| 平湖市| 阿城市|