1. 程式人生 > >01-你真的瞭解併發嗎

01-你真的瞭解併發嗎

01-你真的瞭解併發嗎

我把併發分為四個階段:

第一個階段是,熟練掌握併發相關的API,能夠完成基本的併發程式設計;也就是我們所熟悉的繼承Thread也好,實現Rannable介面也好,使用各種的鎖,根號中期,註冊佇列,等等,你要熟練掌握這些和併發相關的API,這是第一個階段。

我們會用這些API還不行,我們要掌握這些API實現的原理,所以,第二個階段是,熟讀API原始碼,掌握其原理;瞭解了這些原理之後,對我們來說,無論是深入理解併發也好,或者說以後我們的程式設計也好,都是有非常大的幫助的,這是第二個階段。

Java的執行是基於JVM的,那麼,JVM是如何解讀多執行緒的呢?如何解讀我們的併發程式碼呢?

這就需要我們深入理解Java虛擬機器的記憶體模型,以及Java虛擬機器執行多執行緒的執行引擎,等等,就是,關於虛擬機器相關的對執行緒的一些支援,這就深入到了Java虛擬機器的層次,這就是第三個階段。

Java虛擬機器是執行在作業系統上的,第四個階段就是,作業系統對併發的支援。

這是學習併發的四個階段。

我們知道了併發學習的四個階段,那麼,我們為什麼要學習併發?

我們有沒有見過併發的場景呢?其實併發是無處不在的,比如,淘寶的雙十一,就是一個非常高的併發量,就是很多人同時去訪問一個網站,而這個網站卻能夠支撐大量的併發訪問,這就是一個併發的場景,細緻的說,web容器、資料庫伺服器,等等各類的伺服器軟體,都是支援併發的,那麼,併發的效能就直接的影響到軟體的效能,所以,併發程式設計在整個併發應用的場景下是非常關鍵的,除了我們剛剛說的各種服務應用之外,那麼,還有沒有其他的地方用到併發呢?其實也是非常多的,剛剛說的是服務端,那,我們說個客戶端,eclipse就是一個客戶端應用,它也有大量的併發場景,比如說,我們在編輯程式碼的時候,它可以做很多的事情,比如說,可以同時執行一個web服務,也可以做很多的事情,比如說它在進行編譯,等等,總之它會做很多的事情,甚至可以說到底層的垃圾回收,所以,任何一個我們可以說Java應用都是多執行緒的,也都是處於併發的,關於多執行緒和併發,我們後面會詳細的瞭解。也就是說,併發場景在我們的生活中是無時無刻不在發生的,所以,我們要學習併發程式設計。那麼,我們為什麼會在生活中遇到這麼多的併發?這個也是非常好理解的,源於併發的優點,那麼,併發有哪些優點呢?現在硬體越來越便宜,那麼,我們就可以通過增加硬體的方式,幹嘛呢?我們想提高一個性能,就可以使用多核CPU,使用併發可以發揮出多核處理器的強大的能力,當然了,也不僅僅是多核,我們可以直接說多處理器,能夠發揮多個處理器的強大的運算能力,除了發揮多核處理器的強大能力之外,能夠讓我們的建模更加的簡單,就是所謂的建模的簡單性。

第三個是非同步事件的簡化處理;第四個就是響應更加靈敏的使用者介面;

這些是併發程式設計的一些優點,當然,它的好處遠比這些要多的多,這裡僅僅是相當於給大家舉了幾個例子,

建模的簡單性怎麼理解呢?java是一個面向物件的程式語言,我們程式設計的目的其實就是模擬現實客觀世界的一些東西,那麼,這也就是所謂的建模,我們的生活中是無時無刻不體現著多個執行緒的,我在說話的時候,我同時也在移動滑鼠,這就是一個併發的情景,那麼,我不可能當我滑鼠移動的時候我不說話,當我說話的時候滑鼠不能移動,這顯然是一個非常困難的事情,那麼,生活中無時無刻不面臨著大量的併發,我們程式在建模的過程中,

同樣也需要大量的併發,如果我們不使用併發,那麼,建模就會導致非常的繁瑣,有了併發,就可以讓我們的建模更加簡單化。

第3個跟第2個說的基本上是同一個道理,非同步事件的簡化處理,比如說,我們看Windows就知道了,Windows裡面有一個類似的計劃任務,

在這裡面我們去建立一個計劃任務之後,

它就可以在指定的時間,或者指定的事件上去執行某個事件,

比如我們想定時開啟一個我們的web應用,或者說我們定時的開啟一個數據庫服務,等等,那麼,我們可以去做任何的事情,而,等到時間到了這個觸發點的時候,它就可以觸發這個事件去執行這個事件,那麼,這就是一個所謂的非同步事件,非同步事件的簡化處理。第四個就是響應更加靈敏的使用者介面,這個我們做java開發的朋友肯定是大有體會的,就拿eclipse來說的話,我們在編寫程式碼的過程中,比如說,我們就寫一個web應用,那麼,我們在進行web開發的時候,肯定是邊編寫邊除錯的一個過程,那麼,我們可能就會執行一個web伺服器,比方說Tomcat,我們知道,eclipse是整合Tomcat的,因此就是說,如果單執行緒執行的話,那麼,當我們執行web伺服器的時候,我們就沒有辦法同時寫程式碼了,當我們寫程式碼的時候,我們就沒有辦法同時執行web伺服器,那麼,這樣顯然是不好的。當然了,我們也可以通過java自帶的分析工具來看一下,eclipse到底給我們運行了多少個執行緒,通過jconsole這個命令,

我們知道,JDK中給我們自帶了很多的非常好用的監控工具,我們就可以通過這些工具來進行監控我們的Java應用,如果大家對Java的這些監控工具比較感興趣的話,可以參考我之間的“深入理解Java虛擬機器”這個課程,這裡面就非常詳細的講解了Java虛擬機器的一些工具。

我們看到,這就是jconsole,

我們在這裡可以選擇我們的本地程序,

這個地方其實eclipse沒有顯示出來它的名字,我們知道,它就是我們所要看到的,點進去就可以了

可以看到有對記憶體的監控,對執行緒的監控等等,我們就來看對執行緒的監控

我們發現目前有41個執行緒在執行。也就是說,我們看似表面平靜的eclipse,其實,目前它有41個後臺執行緒在不停的在執行著

所以,就是說,我們通過多執行緒可以響應更加靈敏的使用者介面,就是說,如果我們只有單個執行緒的話,那麼

在執行我們這裡所看到的第一個執行緒的時候,就沒有辦法再同時執行後面的執行緒了,那麼,我們在執行

這麼一個操作(建立一個工程)的時候,那麼,我們就需要等待其他的執行緒執行完畢了之後才能夠執行,也就是沒有所謂的執行緒了,就是,等待其他的任務執行完畢了我們再來執行這個,那麼,可以說是相當相當痛苦的一件事。

這就是併發的優勢。

那麼,既然併發這麼強大了,那麼,我們學習併發又有哪些好處呢?這個問題也是非常好解釋的,我們知道併發的功能非常的強大,用的場景也非常的多,那麼,對於我們找工作,面試就非常的的新入手了;我們之前也提到了,我們要熟讀併發的API原始碼,掌握併發的原理,掌握了併發的原理之後,肯定就瞭解了併發變成的原理,提高程式碼的編寫能力,瞭解了原理之後,那麼,排除問題就很容易了,解決工作中遇到的併發問題,也就是併發的一些缺點。其實,人都是有目標的有信仰的,我們做java開發,從技術角度來講,我們都希望自己能夠成長為一名系統架構師,那麼,從java的開發者到系統架構師,那麼,可以說,併發這一塊是必須要經歷的過程,所以,通過我們的學習,可以幫助你更塊的達到你成為系統架構師的目標。

說完這麼多好處了,那麼,併發有沒有缺點呢?當然也是有的,我們就簡單的列舉一下,當然,併發的缺點也並非是無可避免的,都是可以通過一些手段一些方法來儘可能的避免併發中的缺點。

首先,併發肯定是有安全性問題。後面有很長的一段時間我們會不斷的提及安全性問題,我們知道執行緒安全性問題是執行緒的一個非常大的一個問題。第二個是活躍性問題。這個可能很多朋友沒有聽說過,這個後面也會給大家詳細的去說明,這裡僅僅是給大家列出來這麼一回事,那麼,簡單的來說,什麼叫活躍性問題呢?活躍性與之對應的就是不活躍,不活躍就是不執行,那麼,多個執行緒在執行的過程中,我們知道,它是去搶佔CPU的,那麼,畫個圖,

比如這是打菜的視窗,全學校有很多人都來買菜,這是一個秩序非常混亂的學校,誰能夠搶到誰就去買

更有些素質不高的人,他買到了之後,他也不走,所以就導致了,不停的有人在去搶,不停的有人再去往這個視窗上搶,那麼,誰搶到誰就買菜,買完菜他不走,接著再去搶,因此,這就很有可能會導致一個問題,一個什麼問題呢?可能就有這麼幾個學生,他就是始終搶不到,買不上菜,於是就導致了一個問題,就是所謂的飢餓問題,這也是執行緒中的一個術語一個概念叫做飢餓,那麼,處於飢餓狀態他就不活躍,這就是一個活躍性問題,當然了,除了飢餓以外,還有我們所熟悉的,像死鎖,等等,都是活躍性問題的一個典型的問題。

第三個就是效能問題,其實我們列出來的併發的缺點也好,優點也好,在我們後面的內容中都會詳細的瞭解這些東西,效能問題我們這裡先不說,其實,就是我們後面所要討論的“執行緒一定快嗎?”其實作為有經驗的開發人員來講,心裡面是非常清楚的,執行緒不一定快,為什麼?因為執行緒之間切換也是有一定的效能開銷的。

本套課程所要講解的思路:我們舉個例子,我們以執行緒安全性問題來說明,我們授課的思路,比如說要講執行緒安全性問題,那麼,首先我們就要先來建立執行緒,那麼,建立執行緒的多種方式,然後,每一種方式有哪些優缺點,我們要經常使用哪種方式呀等等,然後,建立完這個執行緒之後,我們開始模擬多執行緒執行,然後我們可能會舉一個例子,比如說,多個視窗賣票,也是一個非常經典的例子,然後,賣票肯定會遇到一個問題,就是所謂的執行緒安全性問題的引入,引入完之後,我們要解決,提出解決方案,比如這裡提出來一種方法,我們可以使用synchronized來進行解決,然後下面就是解決執行緒安全性問題,在提出解決方案中,我們可能會提出來非常多的方案,使用多種解決方案來解決執行緒安全性問題,接著我們就需要了解如何解決的,解決的原因,比如,我們要了解synchronized的原理,synchronized的原理我們可能就要深入到Java虛擬機器的層面來進行了解,因此,可能我們在往下了解其他的,如果我們有原始碼的話,我們先了解它的原始碼,然後接著在走Java虛擬機器的層面,就直接看Java虛擬機器的指令,然後分析它的執行,也就是說,可以非常顯然的看出來,我們是由淺入深,

因此我們後面,也會說到這個問題,就是適合的人群。