標籤:
對程式設計語言的基礎知識:分支、選擇、迴圈、物件導向等基本概念後,我們需要對java進階編程有一定的學習,這裡不可避免的要接觸到多線程開發。
由於多線程開發整體的系統比較大,我會寫一個系列的文章總結介紹 多線程開發的概念、使用、線程狀態、同步、線程池。希望與大家共勉。
在第一部分,也就是本節我們先介紹下 什麼是多線程程式、線程和進程又是什麼,以及為什麼要搞多線程。
(一)什麼是多線程程式
多線程聽上去是非常專業的概念,其實非常簡單,我們在日常生活中,經常的接觸到多線程。
比如
(1)在工廠,工人努力工作,分工明確。一些工人準備生產資料(混凝土、鋼筋、磚頭),另外一些工人挖掘地基,還有些工人負責平常無聊的看管,後勤的保障(有點像守護進程,這個後面會專門講到)。他們總體來說就是把一件事分成若干的工作,然後派不同的人去做,最後使工作得到完善的解決。(一個工人算一條線程)
(2)一個學生完成晚上寫的作業,有語、數、外的作業。這名學生寫了一半的語文作業後,有一道題不會做,先去完成數學作業,接著再完成英語作業,最後等到家長回來完成語文作業。(一門作業算一條線程)
主要是有這兩種情況的多線程,
一種是上邊有多個工人(多處理器),各個工人間的工作影響不大,不會因為其中一個工人的努力工作,而導致另外一個工作停歇。
另外一種就是下邊的寫作業形式(單一處理器,只有一個人在做作業),雖然我們有多個作業需要在今天晚上完成(執行),但是某一個時刻我們只能做一件事,當遇到某種情況(例如不會做、或者心情不好)我們隨意的切換到其他的科目,然後開始其他的工作,因為某些原因(如有人可以出現輔導),那麼我們又可以切換回來,繼續做一開始未完成的事情,直到所有的事情都解決完為止。這裡要區分一下:寫作業的例子看著有點像單線程模式的例子,實則不然,單線程只能按照某種既定的順序,順序完成事情,比如語文->外語->數學。遇到困難時(不會做),並不能因為某種原因,而隨意的切換,只能苦苦等待。而多線程則可根據環境動態轉換,如他們之間的順序如語文->外語->數學->語文->外語->外語->數學 這樣。
這種一次做多件事的情況就是多線程(包含短時間內快速的切換,形成一次做多件事的感覺),下面介紹進程和線程,從電腦的角度來談談編程中多線程的概念。
(二)線程和進程又是什麼
進程: 對於一個OS,如果有一個程式在記憶體中開始運行,我們就可以說這個啟動並執行程式就是一個進程。這個進程擁有自己獨立的功能,並且是OS調度和分配資源的一個獨立單位。
對於進程有三個特點
(1)獨立性:進程是系統中獨立存在的一個實體,擁有自己的資源的,沒有自身的允許的話,其他使用者進程是不能訪問他內部的。
(2)動態性:進程是有生命週期的,他是在OS中活動的一個指令集合。而程式只是一個靜態指令集合。
(3)並發性:在只有一個處理器時,多個進程間也可以並發執行,互相併不影響。(進程間相互輪換執行,如同同時進行一般)
線程:線程是進程執行單元,也可以說是一個輕量級的進程。就像OS中進程是獨立的一樣,進程中的各個線程也是獨立的。每個線程都有自己獨立的堆棧及其他資源。互相併不受影響。而進程(這些線程的擁有者)的所有系統資源,被它包含的所有線程所共有分享。
線程也是獨立的,他並不知道當前進程中其他線程的存在,而當前線程是否被執行,則與進程類似,是搶佔式的。當前進程搶到了OS的執行權,而進程中的某一條線程又搶到了,當前可執行檔權利(其他線程和進程被掛起)。
多線程就是一個進程中,可以有多個並發執行的獨立的任務,每一個任務可以說就是一個線程。
他們的關係:
一個OS下邊可以有若干的進程(但是至少要有一個進程)。
每一個進程下邊又有若干的線程(至少要有一條線程)。
(三)為什麼要搞多線程呢?
最最最核心的原因就是:提高工作效率,不要出現閑時等待,各個線程搶佔式的工作。試想下,如果我們遇到什麼問題,是應該一直苦苦等待(是什麼都不做的等待)下去效能高呢,還是快速的切換到其他工作上去,我想在大部分的情況下都是快速搶佔吧。(有時可能會出現,你剛剛切換,原來苦苦等待的事情剛剛結束。。。。這種碰巧的情況),舉個實際點的例子,當我們查詢某一個資料時,這個資料可能非常大,我們需要等待好久才能在頁面上載入下來,此時倘若單線程苦苦等待時,我們的程式就是被掛死了(試想下沒有響應的情境),直到過去了很久,頁面才被啟用,變成可用的狀態。這期間我們什麼事情也幹不了(對該程式),這時的情境效率很低下,而且非常不友好。
倘若有很好的多線程支援的話,那麼在載入資料、繪製圖片時,我們還可以隨意的切換程式,並不影響其他的操作,從而提高效能。於此同時,由於多線程共用父進程的其他所有資源,所以線程間可以很好的交流資料(資料共用和通訊),並且新開闢的線程(新開闢的任務),OS並不會為該進程分配大量的資源(相對於為新開闢任務而建立新進程而言)。
總結一下有如下幾個優點
1、線程間可以很好的共用記憶體資源,進程間是完全獨立記憶體的,所以不方便。(前文中提到線程間是相互獨立的,除非一進程允許,否則其他的進程是不允許直接存取它地址的)
2、系統建立新線程的開銷,新建立進程的開銷要小的多,因此可大大降低多並發的代價。
3、在編碼時,我們可以通過類庫和代碼很好的管理各個線程,而不是直接通過作業系統來指揮當前執行的進程。從而大大的方便了我們可以處理並發任務的執行。
Java多線程開發系列之一:走進多線程