java多執行緒詳解(併發,並行,同步)

fly_zhyu發表於2017-07-04

並行和併發:

引子:前面講到程式的執行流程的時候,說程式在沒有流程控制前提下,程式碼都是從上而下逐行執行的。
需求:現在需要設計一個程式想要完成邊執行遊戲,邊播放歌的功能,怎麼設計?


要解決上述問題,我們們得使用多程式或者多執行緒來解決.

併發和並行是即相似又有區別(微觀概念):
並行:指兩個或多個事件在同一時刻點發生;
併發:指兩個或多個事件在同一時間段內發生。
在作業系統中,在多道程式環境下,併發性是指在一段時間內巨集觀上有多個程式在同時執行,但在單CPU系統中,每一時刻卻僅能有一道程式執行(時間片),故微觀上這些程式只能是分時地交替執行。
倘若計算機系統中有多個CPU,則這些可以併發執行的程式便可被分配到多個處理器上,實現多工並行執行,即利用每個處理器來處理一個可併發執行的程式,這樣,多個程式便可以同時執行,因為是微觀的,所以大家在使用電腦的時候感覺就是多個程式是同時執行的。
所以,大家買電腦的時候喜歡買“核”多的,其原因就是“多核處理器”電腦可以同時並行地處理多個程式,從而提高了電腦的執行效率。
單核處理器的計算機肯定是不能並行的處理多個任務的,只能是多個任務在單個CPU上併發執行。
同理,執行緒也是一樣的,從巨集觀角度上理解執行緒是並行執行的,但是從微觀角度上分析卻是序列執行的,即一個執行緒一個執行緒的去執行,當系統只有一個CPU時,執行緒會以某種順序執行多個執行緒,我們把這種情況稱之為執行緒排程。
時間片即CPU分配給各個程式的執行時間(很小的概念).

程式和執行緒:

程式是指一個記憶體中執行中的應用程式。每個程式都有自己獨立的一塊記憶體空間,一個應用程式可以同時啟動多個程式。比如在Windows系統中,一個執行的abc.exe就是一個程式。
那麼我們此時就可以處理同時玩遊戲和聽音樂的問題了,我們可以設計成兩個程式,一個專門負責玩遊戲,一個專門負責聽音樂。
但是問題來了,要是要設計一個植物大戰殭屍遊戲,我得開N個程式才能完成多個功能,這樣的設計顯然是不合理的。
更何況大多數作業系統都不需要一個程式訪問其他程式的記憶體空間,也就是說程式之間的通訊很不方便。
此時我們得引入“執行緒”這門技術,來解決這個問題。
執行緒是指程式中的一個執行任務(控制單元),一個程式可以同時併發執行多個執行緒,如:多執行緒下載軟體。
多工系統,該系統可以執行多個程式,一個程式也可以執行多個任務,一個程式可以包含多個執行緒.
一個程式至少有一個執行緒,為了提高效率,可以在一個程式中開啟多個執行任務,即多執行緒。
多程式:作業系統中同時執行的多個程式。
多執行緒:在同一個程式中同時執行的多個任務。
我們檢視Windows環境下的工作管理員:
  在作業系統中允許多個任務,每一個任務就是一個程式,每一個程式也可以同時執行多個任務,每一個任務就是執行緒。
程式與執行緒的區別:
程式:有獨立的記憶體空間,程式中的資料存放空間(堆空間和棧空間)是獨立的,至少有一個執行緒。
執行緒:堆空間是共享的,棧空間是獨立的,執行緒消耗的資源也比程式小,相互之間可以影響的,又稱為輕型程式或程式元。
因為一個程式中的多個執行緒是併發執行的,那麼從微觀角度上考慮也是有先後順序的,那麼哪個執行緒執行完全取決於CPU排程器(JVM來排程),程式設計師是控制不了的。
我們可以把多執行緒併發性看作是多個執行緒在瞬間搶CPU資源,誰搶到資源誰就執行,這也造就了多執行緒的隨機性。
Java程式的程式(Java的一個程式執行在系統中)裡至少包含主執行緒和垃圾回收執行緒(後臺執行緒)。
執行緒排程:
計算機通常只有一個CPU時,在任意時刻只能執行一條計算機指令,每一個程式只有獲得CPU的使用權才能執行指令.
所謂多程式併發執行,從巨集觀上看,其實是各個程式輪流獲得CPU的使用權,分別執行各自的任務.
那麼,在可執行池中,會有多個執行緒處於就緒狀態等到CPU,JVM就負責了執行緒的排程.
JVM採用的是搶佔式排程,沒有采用分時排程,因此可以能造成多執行緒執行結果的的隨機性。
多執行緒優勢:

多執行緒作為一種多工、併發的工作方式,當然有其存在優勢:
①  程式之前不能共享記憶體,而執行緒之間共享記憶體(堆記憶體)則很簡單。
② 系統建立程式時需要為該程式重新分配系統資源,建立執行緒則代價小很多,因此實現多工併發時,多執行緒效率更高.
③ Java語言本身內建多執行緒功能的支援,而不是單純第作為底層系統的排程方式,從而簡化了多執行緒程式設計.
CS遊戲/單行道和多行道
多執行緒下載:可以理解為一個執行緒就是一個檔案的下載通道,多執行緒也就是同時開起好幾個下載通道。當伺服器提供下載服務時,使用下載者是共享頻寬的,在優先順序相同的情況下,總伺服器會對總下載執行緒進行平均分配。
不難理解,如果你執行緒多的話,那下載的越快。現流行的下載軟體都支援多執行緒。
多執行緒是為了同步完成多項任務,不是為了提供程式執行效率,而是通過提高資源使用效率來提高系統的效率。
所以現在大家買電腦的時候,也應該看看CPU的執行緒數。
java操作程式:
  在Java程式碼中如何去執行一個程式(簡單講解,獲取程式中的資料(IO)).
  方式1:Runtime類的exec方法:
  方式2:ProcessBuilder的start方法:


建立和啟動執行緒:

方式1:繼承Thread類;
步驟:
1):定義一個類A繼承於java.lang.Thread類.
2):在A類中覆蓋Thread類中的run方法.
3):我們在run方法中編寫需要執行的操作---->run方法裡的,執行緒執行體.
4):在main方法(執行緒)中,建立執行緒物件,並啟動執行緒.
    建立執行緒類物件:                              A類   a  =  new   A類();
    呼叫執行緒物件的start方法:     a.start();//啟動一個執行緒
注意:千萬不要呼叫run方法,如果呼叫run方法好比是物件呼叫方法,依然還是隻有一個執行緒,並沒有開啟新的執行緒.

方式2:實現Runnable介面;
執行緒類(java.lang.Thread): Thread類和Thread的子類才能稱之為執行緒類. 閱讀API.
別忘了主執行緒(mainf方法執行,表示主執行緒).

步驟:
1):定義一個類A實現於java.lang.Runnable介面,注意A類不是執行緒類.
2):在A類中覆蓋Runnable介面中的run方法.
3):我們在run方法中編寫需要執行的操作---->run方法裡的,執行緒執行體.
4):在main方法(執行緒)中,建立執行緒物件,並啟動執行緒.
     建立執行緒類物件:                       Thread  t = new Thread(new  A());    
     呼叫執行緒物件的start方法:          t.start();




相關文章