溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java線程之間的共享與協(xié)作是什么

發(fā)布時間:2022-07-02 10:12:00 來源:億速云 閱讀:129 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“Java線程之間的共享與協(xié)作是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Java線程之間的共享與協(xié)作是什么”吧!

    一、進(jìn)程和線程

    1、進(jìn)程是程序運(yùn)行資源分配的最小單位

    進(jìn)程是操作系統(tǒng)進(jìn)行資源分配的最小單位,其中包括:CPU、內(nèi)存空間、磁盤IO 等、同一進(jìn)程中的多條線程共享該進(jìn)程中的全部系統(tǒng)資源,而進(jìn)程和進(jìn)程直接是相互獨(dú)立的。進(jìn)程是具有一定獨(dú)立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運(yùn)行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨(dú)立單位。

    進(jìn)程是程序在計(jì)算機(jī)上的一次執(zhí)行活動。當(dāng)你運(yùn)行一個程序,你就啟動了一個進(jìn)程。顯然程序是死的、靜態(tài)的、進(jìn)程是活動的、動態(tài)的。進(jìn)程可以分為系統(tǒng)進(jìn)程和用戶進(jìn)程。凡是用于完成操作系統(tǒng)的各種功能的進(jìn)程就是系統(tǒng)進(jìn)程,它們是處于運(yùn)行狀態(tài)下的操作系統(tǒng)本身,用戶進(jìn)程就是所有由你啟動的進(jìn)程。

    2、線程是CPU 調(diào)度的最小單位,必須依賴于進(jìn)程而存在

    線程是進(jìn)程的一個實(shí)體,是CPU調(diào)度和分派的基本單位,它是比經(jīng)常更小的、能夠獨(dú)立運(yùn)行的基本單位。線程自己基本上不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源(如程序計(jì)數(shù)器,一組寄存器和堆棧),但是它可以與同一個進(jìn)程的其他線程共享進(jìn)程所擁有的全部資源。

    3、線程無處不在

    任何一個程序都必須創(chuàng)建線程,特別是Java不管任何程序都必須啟動一個main函數(shù)的主線程;Java web開發(fā)的定時任務(wù)、定時器、JSPServlet、異步消息處理機(jī)制,遠(yuǎn)程訪問接口 RM 等,任何一個監(jiān)聽事件,onClick的觸發(fā)事件等都離不開線程和并發(fā)的知識。

    二、CPU 核心數(shù)和線程數(shù)的關(guān)系

    1、多核心

    多核心:也指單芯片多處理器(Chip Multiprocessors,簡稱 CMP),CMP是由美國斯坦福大學(xué)提出的,其思想是將大規(guī)模并行處理器中的SMP(對稱處理器)集成到同一芯片內(nèi),各個處理器并行執(zhí)行不同的進(jìn)程。這種依靠多個CPU同時并行的運(yùn)行程序是實(shí)現(xiàn)超高速計(jì)算的一個重要方向,稱為并行處理。

    2、多線程

    多線程Simultaneous Multithreading.簡稱 SMT.讓同一個處理器上的多個線程同步執(zhí)行并共享處理器的執(zhí)行資源。

    3、核心數(shù)、線程數(shù)

    核心數(shù)、線程數(shù):目前主流CPU都是多核的。增加核心數(shù)目的就是為了增加線程數(shù),因?yàn)椴僮飨到y(tǒng)是通過線程來執(zhí)行任務(wù)的,一般情況下它們是1:1對應(yīng)關(guān)系,也就是說四核 CPU一般擁有四個線程。但Intel引入超線程技術(shù)后,使核心數(shù)與線程數(shù)形成了1:2的關(guān)系。

    Java線程之間的共享與協(xié)作是什么

    三、CPU 時間片輪轉(zhuǎn)機(jī)制

    我們平時在開發(fā)的時候,感覺并沒有受CPU 核心數(shù)的限制,想啟動線程就啟動線程,哪怕是在單核CPU 上,為什么?這是因?yàn)椴僮飨到y(tǒng)提供了一種CPU 時間片輪轉(zhuǎn)機(jī)制。

    時間片輪轉(zhuǎn)調(diào)度是一種最古老、最簡單、最公平且使用最廣的一種算法,又稱RR 調(diào)度。每個進(jìn)程被分配一個時間段,稱作它的時間片,即該進(jìn)程運(yùn)行運(yùn)行的時間。

    四、并行和并發(fā)

    我們舉個例子,如果有條高速公路A,上面有4條車道,那么最大并行車輛就是4輛,這條高速公路同時并排行走的車輛小與等于4的時候,車輛就可以并行行駛。CPU也是這個原理,一個CPU相當(dāng)于一條高速公路,核心數(shù)或線程數(shù)就相當(dāng)于并排可以通行的車輛;而多個CPU就相當(dāng)于有多條高速公路,而每個高速公路并排有多個車道。

    當(dāng)談?wù)?strong>并發(fā)的時候,一定要加個單位時間,也就是說單位時間內(nèi)并發(fā)量是多少?離開單位時間其實(shí)是沒有意義的。

    俗話說一心不能二用,這對計(jì)算機(jī)也一樣,原則上一個CPU只能分配給一個進(jìn)程,以便運(yùn)行這個進(jìn)程。我們通常用的計(jì)算機(jī)只有一個CPU,也就是說只有一顆心,要讓它一心多用同時運(yùn)行多個進(jìn)程,就必須使用并發(fā)技術(shù)。實(shí)現(xiàn)并發(fā)技術(shù)相當(dāng)復(fù)雜,最容易理解的是“時間片輪轉(zhuǎn)進(jìn)程調(diào)度算法”。

    1、并發(fā)

    并發(fā):指應(yīng)用能夠交替執(zhí)行不同的任務(wù),比如單CPU核心下執(zhí)行多線程并非是同時執(zhí)行多個任何,如果你開兩個線程執(zhí)行,就是在你幾乎不可察覺的速度不斷去切換執(zhí)行這兩個任務(wù),以達(dá)到“同時執(zhí)行”效果,只是計(jì)算機(jī)的執(zhí)行速度太快,我們無法察覺到而已。

    2、并行

    并行:指應(yīng)用能夠同時執(zhí)行不同的任務(wù),例:吃飯的時候可以邊吃飯邊看電視,這兩件事可以同時執(zhí)行。

    **并發(fā)和并行兩者的區(qū)別就是:一個是交替執(zhí)行,一個是同時執(zhí)行**

    Java線程之間的共享與協(xié)作是什么

    五、高并發(fā)編程

    由于多核CPU的誕生,多線程、高并發(fā)的編程越來越受重視和關(guān)注。

    1、CPU 資源利用的充分

    從上面CPU的介紹,可以看出現(xiàn)在市面上沒有CPU的內(nèi)核不使用多線程并發(fā)機(jī)制的,特別是服務(wù)器還不止一個CPU。程序的基本調(diào)度單元是線程,一個線程也只能在一個一個CPU 的一個核的一個線程跑,如果你是個i3的CPU的話,最差也是雙核心4線程的運(yùn)算能力:如果是一個線程的話,那就會浪費(fèi)釣3/4的CPU性能:如果設(shè)計(jì)一個多線程的話,那它就可以同時在多個CPU 的多個核的多個線程上跑,可以充分的利用CPU,減少CPU的空閑時間,發(fā)揮它的運(yùn)算能力,提高并發(fā)量。

    2、加快用戶響應(yīng)時間

    比如我們經(jīng)常使用的下載功能,很多朋友都會開通某一個會員,因?yàn)闀T版本啟用了多個線程去下載,誰都無法忍受一個線程去下,為什么呢?因?yàn)槎嗑€程下載快啊。

    我們做程序開發(fā)的時候,網(wǎng)頁速度提升1s,如果用戶量大的話,就能增加不少轉(zhuǎn)換量。我們經(jīng)常瀏覽的網(wǎng)頁中,瀏覽器在加載頁面的時候,都會去多開幾個線程去加載網(wǎng)絡(luò)資源,提升網(wǎng)站的相應(yīng)速度。多線程和高并發(fā),在計(jì)算機(jī)中,無處不在。

    3、使代碼模塊化、異步化、簡單化

    例如我們做一個電商項(xiàng)目,下訂單和給用戶發(fā)送短信、郵件就可以進(jìn)行拆分,將給用戶發(fā)送短信、郵件這兩個步驟獨(dú)立成兩個單獨(dú)的模塊,交給其他線程去執(zhí)行。這樣即增加了異步的操作,提示了系統(tǒng)性能,又使程序模塊化,清晰化和簡單化。

    六、多線程注意事項(xiàng)

    1、線程之間的安全性

    在同一個進(jìn)程里面的多線程是資源共享的,也就是都可以訪問同一個內(nèi)存地址當(dāng)中的一個變量。

    例如:若每個線程中對全局變量、靜態(tài)變量只讀操作,而無寫操作,一般來說,這個全局變量是線程安全的;若有多個線程同時執(zhí)行寫操作,一般都需要考慮線程同步,否則就可能影響線程安全。

    2、線程之間的死鎖

    為了解決線程之間的安全性引入了Java 鎖的機(jī)制,而一不小心就會產(chǎn)生Java 線程死鎖的多線程問題,因?yàn)椴煌木€程都在等待哪些根本不可能被釋放的鎖,從而導(dǎo)致所有的工作都無法完成。

    假設(shè)有兩個饑餓的人,他們必須共享刀叉并輪流吃飯,他們都需要獲得兩個鎖,共享刀和共享叉。假如線程A獲得了刀,而線程B獲得了叉。線程A就會進(jìn)入阻塞狀態(tài)來等待獲得叉,而線程B則主帥來等待線程A所擁有的刀。這只是人為設(shè)計(jì)的例子,單盡管在運(yùn)行時很難探測到,這類情況卻時常發(fā)生。

    3、線程多了會將服務(wù)資源耗盡形成死機(jī)、當(dāng)機(jī)

    線程數(shù)太多有可能造成系統(tǒng)創(chuàng)建大量線程,而導(dǎo)致消耗完系統(tǒng)內(nèi)存以及CPU的“過渡切換”,造成系統(tǒng)的死機(jī),那么我們改如果解決這類問題呢?

    某些系統(tǒng)資源是有限的,如文件描述。多線程程序可能耗盡資源,因?yàn)槊總€線程都可能希望有一個這樣的資源。如果線程數(shù)相當(dāng)大,或者某個資源的侯選線 程數(shù)遠(yuǎn)遠(yuǎn)超過了可用的資源數(shù)則最好使用資源池。一個最好的示例是數(shù)據(jù)庫連接池。只要線程需要使用一個數(shù)據(jù)庫連接,它就從池中取出一個,使用以后再將它返回池中。資源池也稱為資源庫。

    多線程應(yīng)用開發(fā)的注意事項(xiàng)很多,希望大家在日后的工作中可以慢慢體會它 的危險(xiǎn)所在。

    七、多線程注意事項(xiàng)

    線程之間相互配合,完成某項(xiàng)工作,比如:一個線程修改了一個對象的值, 而另一個線程感知到了變化,然后進(jìn)行相應(yīng)的操作,整個過程開始于一個線程, 而最終執(zhí)行又是另一個線程。前者是生產(chǎn)者,后者就是消費(fèi)者,這種模式隔離了 “做什么”(what)和“怎么做”(How),簡單的辦法是讓消費(fèi)者線程不斷地 循環(huán)檢查變量是否符合預(yù)期在 while 循環(huán)中設(shè)置不滿足的條件,如果條件滿足則 退出 while 循環(huán),從而完成消費(fèi)者的工作。

    卻存在如下問題:

    • 難以確保及時性。

    • 難以降低開銷。如果降低睡眠的時間,比如休眠 1 毫秒,這樣消費(fèi)者能 更加迅速地發(fā)現(xiàn)條件變化,但是卻可能消耗更多的處理器資源,造成了無端的浪費(fèi)。

    等待/通知機(jī)制:是指一個線程 A 調(diào)用了對象 O 的 wait()方法進(jìn)入等待狀態(tài),而另一個線程 B 調(diào)用了對象 O 的 notify()或者 notifyAll()方法,線程 A 收到通知后從對象 O 的 wait() 方法返回,進(jìn)而執(zhí)行后續(xù)操作。上述兩個線程通過對象 O 來完成交互,而對象 上的 wait()和 notify/notifyAll()的關(guān)系就如同開關(guān)信號一樣,用來完成等待方和通 知方之間的交互工作。

    notify():通知一個在對象上等待的線程,使其從 wait 方法返回,而返回的前提是該線程獲取到了對象的鎖,沒有獲得鎖的線程重新進(jìn)入 WAITING 狀態(tài)。

    notifyAll():通知所有等待在該對象上的線程

    wait():調(diào)用該方法的線程進(jìn)入 WAITING 狀態(tài),只有等待另外線程的通知或被中斷 才會返回.需要注意,調(diào)用 wait()方法后,會釋放對象的鎖。

    wait(long):超時等待一段時間,這里的參數(shù)時間是毫秒,也就是等待長達(dá)n 毫秒,如果沒有 通知就超時返回。

    wait (long,int):對于超時時間更細(xì)粒度的控制,可以達(dá)到納秒

    等待和通知的標(biāo)準(zhǔn)范式 等待方遵循如下原則。

    • 獲取對象的鎖。

    • 如果條件不滿足,那么調(diào)用對象的 wait()方法,被通知后仍要檢查條件。

    • 條件滿足則執(zhí)行對應(yīng)的邏輯。

    Java線程之間的共享與協(xié)作是什么

    通知方遵循如下原則:

    • 獲得對象的鎖。

    • 改變條件。

    • 通知所有等待在對象上的線程。

    Java線程之間的共享與協(xié)作是什么

    在調(diào)用 wait()、notify()系列方法之前,線程必須要獲得該對象的對象級別鎖,即只能在同步方法或同步塊中調(diào)用 wait()方法、notify()系列方法,進(jìn) 入 wait()方法后,當(dāng)前線程釋放鎖,在從 wait()返回前,線程與其他線程競 爭重新獲得鎖,執(zhí)行 notify()系列方法的線程退出調(diào)用了 notifyAll 的 synchronized 代碼塊的時候后,他們就會去競爭。如果其中一個線程獲得了該對象鎖,它就會 繼續(xù)往下執(zhí)行,在它退出 synchronized 代碼塊,釋放鎖后,其他的已經(jīng)被喚醒的 線程將會繼續(xù)競爭獲取該鎖,一直進(jìn)行下去,直到所有被喚醒的線程都執(zhí)行完畢。

    notify 和 notifyAll 應(yīng)該用誰

    盡可能用 notifyAll(),謹(jǐn)慎使用 notify(),因?yàn)?notify()只會喚醒一個線程,我們無法確保被喚醒的這個線程一定就是我們需要喚醒的線程。

    感謝各位的閱讀,以上就是“Java線程之間的共享與協(xié)作是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Java線程之間的共享與協(xié)作是什么這一問題有了更深刻的體會,具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI