首頁 > 科技

就這一篇輕鬆帶你掌握Java多執行緒的高併發問題,網友:太實用了

2021-06-22 15:51:54

Hello,今天給各位童鞋們分享的是Java多執行緒,趕緊拿出小本子記下來吧

程序

程序的簡單概念

在程序模型中,計算機所有可運行的軟體,通常也包括作業系統,被組織成若干順序程序,簡稱程序(process),一個程序就是一個正在執行程式的示例。

大白話來說,一個程序就相當於我們啟動的項目,或者說開啟工作管理員的時候看到的這些應用都是程序。一個程序主要包括程式計數器、寄存器和變數的當前值

這裡還需要講下的一個概念就是守護程序

停留在後臺處理的程序稱之為守護程序。

程序的狀態

程序的狀態有三個狀態,就緒、運行、阻塞。就緒就是能運行,但是還沒運行,CPU被其它程序佔用了;運行就是該時刻程序已經實際佔用CPU在運行了;阻塞基本上等於暫停了,除非有外界因素干擾,不然該程序就不能運行了。

拿做核酸來講,醫護人員就是CPU,正在做核酸的人就是運行態,在後面排隊的就是就緒態,沒有人逼他自己不想做根本沒有來排隊就是阻塞態。

值得注意的是,這三種狀態是可以互相轉換

運行 》》 阻塞: 當系統發現程序無法再運行下去的時候,或者認為終止程序後就會發生該轉換。運行 《 》 就緒: 這兩個轉換大多數時候是一體的,主要是由系統程序排程程式決定的,程序對於排程的變化基本上是感知不到的。當系統認為這個程序已經長時間佔用CPU了,那麼會根據一定的演算法 重新分配CPU的時間片,此時就會伴隨著狀態的轉變。阻塞 》》就緒: 當程序等待的一個外部事件發生時就會發生次轉換,通俗就是,比如大規模核酸檢測,社群上門提醒,就會去排隊。程序間的通訊方式

程序間的通訊方式有8種,但是忘記在哪本書上看到的這8種的概念,網上雖然有解釋,但是不太權威,就沒寫出來,各位小夥伴暫時就先了解下是哪8種即可。

無名管道,有名管道,高階管道,訊息佇列,訊號量,訊號,共享記憶體和套接字。

執行緒

執行緒基本概念

對於執行緒,查了很久也沒有一個明確的概念,甚至再《現代作業系統中》也是模糊的概念,迷你程序(稱為執行緒)。

用Java程式通俗的來說呢,就是一個程式就是一個程序,然後main方法就是該程序的主執行緒,然後在之後我們會創建多個執行緒。

我們知道,每個程序都有一個地址空間和一個控制執行緒,這裡的主執行緒是不是控制執行緒有待考量。

執行緒的狀態

相較於程序而言,執行緒的狀態有五種。

New: new是指新建了一個執行緒,但是還未啟動。對應到程式碼就是隻是new了一個Thread後,該執行緒就處於新建狀態,此時僅由JVM為其分配記憶體,並初始化其成員變數的值Runnable: 當執行緒呼叫了start()方法後,該執行緒就處於就緒狀態,在等待cpu時間片。在虛擬機器的表現就是Java虛擬機器會為其創建方法呼叫棧和程式計數器,等待排程運行Running: 顧名思義就是程式處於運行狀態,對應到程式碼就是處於就緒狀態的執行緒獲得了CPU,開始執行run()方法的執行緒執行體,則該執行緒處於運行狀態。Blocked: 就是我們經常聽到的阻塞狀態,是指執行緒因為某種原因放棄了cpu使用權,即讓出了cpu timeslice(時間片),暫時停止運行。這種狀態會一直維持到執行緒進入可運行(runnable)狀態,才有機會再次獲取到cpu時間片,從而再次轉到運行(running)狀態Dead: 執行緒結束後的狀態就是死亡狀態對於阻塞狀態而言,分為3種:

等待阻塞: 運行中的執行緒中的執行緒呼叫了object.wait()方法,JVM會把該執行緒放入等待佇列中,使得本執行緒進入阻塞狀態。同步阻塞: 運行中執行緒在獲取物件的同步鎖時,若該同步鎖被別的執行緒佔用,大白話就是說拿不到鎖,JVM會把該執行緒放入鎖池(lock pool)中。其它阻塞: 運行中的執行緒執行Thread.sleep(long ms)後者t.join()方法,亦或是發出了I/O請求時,JVM會把執行緒置為阻塞狀態。當sleep()狀態超時、join()等待執行緒終止或者超時、或者I/O處理完畢時,執行緒重新轉入可運行(runnable)狀態。對於執行緒的Dead狀態而言,方式有以下三種:

正常結束,就是run()或者call()方法執行完成異常結束,執行緒在運行的過程中拋出一個未捕獲的Exception或Error呼叫stop()方法,直接呼叫該執行緒的stop()方法來結束執行緒,但是這種方法容易導致死鎖,所以一般不建議使用執行緒間的通訊方式

執行緒間的通訊方式主要是由3種方式,共享記憶體、訊息傳遞和管道流。

共享記憶體:java裡面一般是使用volatile共享記憶體訊息傳遞:java裡面會使用的方式如wait/notify , join 等方法。管道流:管道輸入/輸出流的形式其它

程序和執行緒的區別

多程序就是作業系統中同時運行的多個程式,多執行緒在同一個程序中同時運行的多個任務。

根本區別:程序是作業系統資源分配的基本單位,而執行緒是處理器任務排程和執行的基本單位

資源開銷:每個程序都有獨立的程式碼和資料空間(程式上下文),程式之間的切換會有較大的開銷;執行緒可以看做輕量級的程序,同一類執行緒共享程式碼和資料空間,每個執行緒都有自己獨立的運行棧和程式計數器(PC),執行緒之間切換的開銷小。

包含關係:如果一個程序內有多個執行緒,則執行過程不是一條線的,而是多條線(執行緒)共同完成的;執行緒是程序的一部分,所以執行緒也被稱為輕權程序或者輕量級程序。

記憶體分配:同一程序的執行緒共享本程序的地址空間和資源,而程序之間的地址空間和資源是相互獨立的

影響關係:一個程序崩潰後,在保護模式下不會對其他程序產生影響,但是一個執行緒崩潰整個程序都死掉。所以多程序要比多執行緒健壯。

執行過程:每個獨立的程序有程式運行的入口、順序執行序列和程式出口。但是執行緒不能獨立執行,必須依存在應用程式中,由應用程式提供多個執行緒執行控制,兩者均可併發執行

執行緒不安全

在《Java併發程式設計實戰》中有這麼一句話

當多個執行緒訪問一個類時,如果不用考慮這些執行緒在運行時環境下的排程和交替進行,並且不需要額外的同步及呼叫方程式碼不必作其它的協調,這個類的行為仍然是正確的,那麼成這個類是執行緒安全的。

通俗一點來說,要想程式碼執行緒安全,其實就是保證狀態的訪問時不出錯的,物件的狀態一般情況下指的是資料。但是資料大多數情況都是共享可變的。

顧名思義,共享指的是執行緒之間是可以訪問到這個變數,可變是是指資料的值是可以被更改的,不是寫死的。

資源

什麼是資源,在《現代作業系統》中的定義是

我們把這裡需要排他性使用的物件稱為資源。資源可以是硬體裝置(如藍光碟機動器)或者是一組資訊(如資料庫中一個加鎖的記錄)......簡單來說,資源就是隨著時間的推移,必須能獲得、使用以及釋放的任何東西

對於這個資源,在java程式裡面是鎖呢,還是指的共享變數呢,我個人覺得更像是鎖,不知道各位小夥伴怎麼看。

並行和併發

併發是指同一個時間段內多個執行緒在執行任務,一般是交替執行;並行是指同一個時刻下多個執行緒同時工作。

在作業系統的層次來看,如果多個執行緒能同時被多個CPU執行,這樣就是並行。併發是多個執行緒被一個CPU按照某一演算法切換執行

好啦,今天的文章就到這裡了,希望能夠幫助到螢幕前迷茫的你們

如何獲取?

轉發分享此文,後臺私信小編:「資料」即可獲取。(注:轉發分享,感謝大家)


IT145.com E-mail:sddin#qq.com