java 線程狀態(tài) java多線程為什么不推薦使用excutor執(zhí)行?
java多線程為什么不推薦使用excutor執(zhí)行?Java中BlockingQueue有兩種主要實現(xiàn):arrayblockingqueue和linkedblockingqueue。Arrayblock
java多線程為什么不推薦使用excutor執(zhí)行?
Java中BlockingQueue有兩種主要實現(xiàn):arrayblockingqueue和linkedblockingqueue。Arrayblockingqueue是由array實現(xiàn)的有界阻塞隊列,必須設(shè)置其容量。linkedblockingqueue是由鏈表實現(xiàn)的有界阻塞隊列。容量可選擇性設(shè)置。如果不設(shè)置,它將是一個無限長的阻塞隊列,最大長度為Integer.MAX[value.
查看new singleexecutor的源代碼,您可以發(fā)現(xiàn)在創(chuàng)建linkedblockingqueue時沒有指定容量。此時,linkedblockingqueue是一個無邊界隊列。對于無邊界隊列,任務(wù)可以連續(xù)添加到隊列中。在這種情況下,由于任務(wù)太多,可能會發(fā)生內(nèi)存溢出。
多個線程可以讀一個變量,只有一個線程可以對這個變量進(jìn)行寫,到底要不要加鎖?
下面簡要說明以下原因:
鎖定是因為操作不是原子的。讓我們用操作一來解釋它??聪旅鎯蓚€圖。
我這個操作需要
看上面的第二個圖,你能很清楚地理解這個過程嗎?
鎖定是為了確保上述三個步驟是原子操作。
回到問題上來,只有一個線程要寫,沒有競爭,所以不需要鎖定。
但是,如果你看第一張圖片,因為主內(nèi)存和本地內(nèi)存的存在
在一個線程寫入后,其他線程無法立即看到它。這就是可見性問題。
添加volatile關(guān)鍵字后,它將在操作后強制工作內(nèi)存和主內(nèi)存同步,以確保其他線程可以立即看到它。
為什么Java堅持多線程不選擇協(xié)程?
Java從發(fā)明的第一天起就被定義為多線程網(wǎng)絡(luò)編程語言。Java最大的特點不是跨平臺,而是它的多線程模型(當(dāng)時,C中沒有線程,正如我們現(xiàn)在看到的,C還沒有出現(xiàn))。因為近二十年來軟件產(chǎn)業(yè)的增長主要來自于網(wǎng)絡(luò)編程。網(wǎng)絡(luò)編程中最常見的模式是客戶機/服務(wù)器(client/server,又稱C/s),這種編程模式需要在服務(wù)器端同時接受客戶機的請求,即具有良好的并發(fā)特性,主要依賴于多線程技術(shù)。Java的主戰(zhàn)場是服務(wù)器端編程。因此,多線程技術(shù)對Java來說是非常重要和不可缺少的。
當(dāng)我們要引入?yún)f(xié)處理時,我們要解決哪些問題。我認(rèn)為這只不過是以下幾點:
節(jié)省資源,重量輕,具體來說:節(jié)省內(nèi)存,每個線程需要分配一段堆棧內(nèi)存,內(nèi)核中的一些資源,節(jié)省分配線程的開銷(創(chuàng)建和銷毀線程每次需要做一個系統(tǒng)調(diào)用),節(jié)省了線程切換帶來的大量開銷,配合NiO實現(xiàn)無阻塞編程,提高了系統(tǒng)的吞吐量,使用起來更方便。另外,async await(異步運行,但寫起來感覺是同步的)我們分開來談。
讓我們從記憶開始。以javaweb編程為例,Tomcat上woker線程池的最大線程數(shù)一般配置在50到500之間(spring boot的默認(rèn)值是200)。也就是說,可以同時接受的請求太多了。如果超過最大值,請求將被拒絕。如果每個線程提供128KB,則500個線程的內(nèi)存消耗約為60MB。如果存在瓶頸,可能在CPU、IO、帶寬、DB-CPU等方面存在瓶頸,但是對于通常為數(shù)GB的Java運行時進(jìn)程來說,內(nèi)存量的增加似乎不是一個大問題。