内射老阿姨1区2区3区4区_久久精品人人做人人爽电影蜜月_久久国产精品亚洲77777_99精品又大又爽又粗少妇毛片

如何才能夠系統(tǒng)地學(xué)習(xí)Java并發(fā)技術(shù)?-創(chuàng)新互聯(lián)

Java并發(fā)編程一直是Java程序員必須懂但又是很難懂的技術(shù)內(nèi)容。

創(chuàng)新互聯(lián)主營(yíng)石河子網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,app軟件定制開(kāi)發(fā),石河子h5小程序制作搭建,石河子網(wǎng)站營(yíng)銷(xiāo)推廣歡迎石河子等地區(qū)企業(yè)咨詢

這里不僅僅是指使用簡(jiǎn)單的多線程編程,或者使用juc的某個(gè)類(lèi)。當(dāng)然這些都是并發(fā)編程的基本知識(shí),除了使用這些工具以外,Java并發(fā)編程中涉及到的技術(shù)原理十分豐富。為了更好地把并發(fā)知識(shí)形成一個(gè)體系,也鑒于本人目前也沒(méi)有能力寫(xiě)出這類(lèi)文章,于是參考幾位并發(fā)編程方面專(zhuān)家的博客和書(shū)籍,做一個(gè)簡(jiǎn)單的整理。

首先說(shuō)一下我學(xué)習(xí)Java并發(fā)編程的一些方法吧。大概分為這幾步:


1、先學(xué)會(huì)最基礎(chǔ)的Java多線程編程,Thread類(lèi)的使用,線程通信的一些方法等等。這部分內(nèi)容需要多寫(xiě)一些demo去實(shí)踐。


2、接下來(lái)可以去使用一些JUC的API,比如concurrenthashmap,并發(fā)工具類(lèi),原子數(shù)據(jù)類(lèi)型等工具,在學(xué)習(xí)這部分內(nèi)容的時(shí)候,你可以搭配一些介紹并發(fā)編程的書(shū)籍和博客一起看,書(shū)籍我當(dāng)時(shí)看的是《Java并發(fā)編程藝術(shù)》,我覺(jué)得略好于《Java并發(fā)編程實(shí)踐》。

我這個(gè)專(zhuān)欄里也整合了一些比較好的博客,所以大家可以不妨先看看。


3、接下來(lái)就要閱讀源碼了,讀源碼部分最主要的就是讀JUC包的源碼,比如concurrenthashmap,阻塞隊(duì)列,線程池等等,當(dāng)然,這些源碼自己讀起來(lái)會(huì)比較痛苦,所以建議跟著博客走。


4、走到這一步,你已經(jīng)理解了Java并發(fā)編程原理,并且可以熟練使用JUC,應(yīng)付面試已經(jīng)足夠了,剩下的事情就是真正把這些東西用到項(xiàng)目中去,我當(dāng)時(shí)在網(wǎng)易實(shí)習(xí)的時(shí)候就用到了JUC的一些內(nèi)容,不得不說(shuō)還是挺有意思的。


下面先介紹一下Java并發(fā)編程的一些主要內(nèi)容,我把它分六個(gè)部分,大家可以參考這幾個(gè)部分的內(nèi)容分別進(jìn)行學(xué)習(xí)。

一:并發(fā)基礎(chǔ)和多線程

首先需要學(xué)習(xí)的就是并發(fā)的基礎(chǔ)知識(shí),什么是并發(fā),為什么要并發(fā),多線程的概念,線程安全的概念等。

然后學(xué)會(huì)使用Java中的Thread或是其他線程實(shí)現(xiàn)方法,了解線程的狀態(tài)轉(zhuǎn)換,線程的方法,線程的通信方式等。

二:JMM內(nèi)存模型

任何語(yǔ)言最終都是運(yùn)行在處理器上,JVM虛擬機(jī)為了給開(kāi)發(fā)者一個(gè)一致的編程內(nèi)存模型,需要制定一套規(guī)則,這套規(guī)則可以在不同架構(gòu)的機(jī)器上有不同實(shí)現(xiàn),并且向上為程序員提供統(tǒng)一的JMM內(nèi)存模型。

所以了解JMM內(nèi)存模型也是了解Java并發(fā)原理的一個(gè)重點(diǎn),其中了解指令重排,內(nèi)存屏障,以及可見(jiàn)性原理尤為重要。

JMM只保證happens-before和as-if-serial規(guī)則,所以在多線程并發(fā)時(shí),可能出現(xiàn)原子性,可見(jiàn)性以及有序性這三大問(wèn)題。

下面的內(nèi)容則會(huì)講述Java是如何解決這三大問(wèn)題的。

三:synchronized,volatile,final等關(guān)鍵字

對(duì)于并發(fā)的三大問(wèn)題,volatile可以保證可見(jiàn)性,synchronized三種特性都可以保證。

synchronized是基于操作系統(tǒng)的mutex lock指令實(shí)現(xiàn)的,volatile和final則是根據(jù)JMM實(shí)現(xiàn)其內(nèi)存語(yǔ)義。

此處還要了解CAS操作,它不僅提供了類(lèi)似volatile的內(nèi)存語(yǔ)義,并且保證操作原子性,因?yàn)樗怯捎布?shí)現(xiàn)的。

JUC中的Lock底層就是使用volatile加上CAS的方式實(shí)現(xiàn)的。synchronized也會(huì)嘗試用cas操作來(lái)優(yōu)化器重量級(jí)鎖。

了解這些關(guān)鍵字是很有必要的。

四:JUC包

在了解完上述內(nèi)容以后,就可以看看JUC的內(nèi)容了。

JUC提供了包括Lock,原子操作類(lèi),線程池,同步容器,工具類(lèi)等內(nèi)容。

這些類(lèi)的基礎(chǔ)都是AQS,所以了解AQS的原理是很重要的。

除此之外,還可以了解一下Fork/Join,以及JUC的常用場(chǎng)景,比如生產(chǎn)者消費(fèi)者,阻塞隊(duì)列,以及讀寫(xiě)容器等。

五:實(shí)踐

上述這些內(nèi)容,除了JMM部分的內(nèi)容比較不好實(shí)現(xiàn)之外,像是多線程基本使用,JUC的使用都可以在代碼實(shí)踐中更好地理解其原理。多嘗試一些場(chǎng)景,或者在網(wǎng)上找一些比較經(jīng)典的并發(fā)場(chǎng)景,或者參考別人的例子,在實(shí)踐中加深理解,還是很有必要的。

六:補(bǔ)充

由于很多Java新手可能對(duì)并發(fā)編程沒(méi)什么概念,在這里放一張不錯(cuò)的思維導(dǎo)圖,該圖簡(jiǎn)要地提幾個(gè)并發(fā)編程中比要重要的點(diǎn),也是比較基本的點(diǎn),在大致了解了這些基礎(chǔ)內(nèi)容以后,才能更好地開(kāi)展后面詳細(xì)內(nèi)容的學(xué)習(xí)。

如何才能夠系統(tǒng)地學(xué)習(xí)Java并發(fā)技術(shù)?

上面講到了學(xué)習(xí)路線,建議大家先跟著這個(gè)路線去看一看本專(zhuān)欄的一些博客,然后再來(lái)看下面這部分內(nèi)容,因?yàn)橄旅娴膬?nèi)容是我基于本專(zhuān)欄所有博客進(jìn)行歸納和總結(jié)的,主要是方便記憶和復(fù)習(xí),也可以讓你把知識(shí)點(diǎn)重新過(guò)一遍,如果你覺(jué)得我的總結(jié)不夠好,你也可以自己做總結(jié),這也是一種不錯(cuò)的學(xué)習(xí)方法,話不多少,咱們接著往下看。

這篇總結(jié)主要是基于我Java并發(fā)技術(shù)系列的文章而形成的的。主要是把重要的知識(shí)點(diǎn)用自己的話說(shuō)了一遍,可能會(huì)有一些錯(cuò)誤,還望見(jiàn)諒和指點(diǎn)。謝謝

更多詳細(xì)內(nèi)容可以查看我的專(zhuān)欄文章:Java并發(fā)技術(shù)指南

https://blog.csdn.net/column/details/21961.html

線程安全

  1. 線程安全一般指多線程之間的操作結(jié)果不會(huì)因?yàn)榫€程調(diào)度的順序不同而發(fā)生改變。

互斥和同步

  1. 互斥一般指資源的獨(dú)占訪問(wèn),同步則要求同步代碼中的代碼順序執(zhí)行,并且也是單線程獨(dú)占的。

JMM內(nèi)存模型

  1. JVM中的內(nèi)存分區(qū)包括堆,棧,方法區(qū)等區(qū)域,這些內(nèi)存都是抽象出來(lái)的,實(shí)際上,系統(tǒng)中只有一個(gè)主內(nèi)存,但是為了方便Java多線程語(yǔ)義的實(shí)現(xiàn),以及降低程序員編寫(xiě)并發(fā)程序的難度,Java提出了JMM內(nèi)存模型,將內(nèi)存分為主內(nèi)存和工作內(nèi)存,工作內(nèi)存是線程獨(dú)占的,實(shí)際上它是一系列寄存器,編譯器優(yōu)化后的結(jié)果。

as-if-Serial,happens-before

  1. as if serial語(yǔ)義提供單線程代碼的順序執(zhí)行保證,雖然他允許指令重排序,但是前提是指令重排序不會(huì)改變執(zhí)行結(jié)果。

volatile

  1. volatile語(yǔ)義實(shí)際上是在代碼中插入一個(gè)內(nèi)存屏障,內(nèi)存屏障分為讀寫(xiě),寫(xiě)讀,讀讀,寫(xiě)寫(xiě)四種,可以用來(lái)避免volatile變量的讀寫(xiě)操作發(fā)生重排序,從而保證了volatile的語(yǔ)義,實(shí)際上,volatile修飾的變量強(qiáng)制要求線程寫(xiě)時(shí)將數(shù)據(jù)從緩存刷入主內(nèi)存,讀時(shí)強(qiáng)制要求線程從主內(nèi)存中讀取,因此保證了它的可見(jiàn)性。
  2. 而對(duì)于volatile修飾的64位類(lèi)型數(shù)據(jù),可以保證其原子性,不會(huì)因?yàn)橹噶钪嘏判驅(qū)е乱粋€(gè)64位數(shù)據(jù)被分割成兩個(gè)32位數(shù)據(jù)來(lái)讀取。

synchronized和鎖優(yōu)化

  1. synchronized是Java提供的同步標(biāo)識(shí),底層是操作系統(tǒng)的mutex lock調(diào)用,需要進(jìn)行用戶態(tài)到內(nèi)核態(tài)的切換,開(kāi)銷(xiāo)比較大。

  2. synchronized經(jīng)過(guò)編譯后的匯編代碼會(huì)有monitor in和monitor out的字樣,用于標(biāo)識(shí)進(jìn)入監(jiān)視器模塊和退出監(jiān)視器模塊,

  3. 監(jiān)視器模塊watcher會(huì)監(jiān)控同步代碼塊中的線程號(hào),只允線程號(hào)正確的線程進(jìn)入。

  4. Java在synchronized關(guān)鍵字中進(jìn)行了多次優(yōu)化。

  5. 比如輕量級(jí)鎖優(yōu)化,使用鎖對(duì)象的對(duì)象頭做文章,當(dāng)一個(gè)線程需要獲得該對(duì)象鎖時(shí),線程有一段空間叫做lock record,用于存儲(chǔ)對(duì)象頭的mask word,然后通過(guò)cas操作將對(duì)象頭的mask word改成指向線程中的lockrecord。

  6. 如果成功了就是獲取到了鎖,否則就是發(fā)生了互斥。需要鎖粗化,膨脹為互斥鎖。

  7. 偏向鎖,去掉了更多的同步措施,檢查mask word是否是可偏向狀態(tài),然后檢查mask word中的線程id是否是自己的id,如果是則執(zhí)行同步代碼,如果不是則cas修改其id,如果修改失敗,則出現(xiàn)鎖爭(zhēng)用,偏向鎖失效,膨脹為輕量級(jí)鎖。

  8. 自旋鎖,每個(gè)線程會(huì)被分配一段時(shí)間片,并且聽(tīng)候cpu調(diào)度,如果發(fā)生線程阻塞需要切換的開(kāi)銷(xiāo),于是使用自旋鎖不需要阻塞,而是忙等循環(huán),一獲取時(shí)間片就開(kāi)始忙等,這樣的鎖就是自旋鎖,一般用于并發(fā)量比較小,又擔(dān)心切換開(kāi)銷(xiāo)的場(chǎng)景。

CAS操作

  1. CAS操作是通過(guò)硬件實(shí)現(xiàn)的原子操作,通過(guò)一條指令完成比較和賦值的操作,防止發(fā)生因指令重排導(dǎo)致的非原子操作,在Java中通過(guò)unsafe包可以直接使用,在Java原子類(lèi)中使用cas操作來(lái)完成一系列原子數(shù)據(jù)類(lèi)型的構(gòu)建,保證自加自減等依賴原值的操作不會(huì)出現(xiàn)并發(fā)問(wèn)題。

  2. cas操作也廣泛用在其他并發(fā)類(lèi)中,通過(guò)循環(huán)cas操作可以完成線程安全的并發(fā)賦值,也可以通過(guò)一次cas操作來(lái)避免使用互斥鎖。

Lock類(lèi)

AQS

  1. AQS是Lock類(lèi)的基石,他是一個(gè)抽象類(lèi),通過(guò)操作一個(gè)變量state來(lái)判斷線程鎖爭(zhēng)用的情況,通過(guò)一系列方法實(shí)現(xiàn)對(duì)該變量的修改。一般可以分為獨(dú)占鎖和互斥鎖。

  2. AQS維護(hù)著一個(gè)CLH阻塞隊(duì)列,這個(gè)隊(duì)列主要用來(lái)存放阻塞等待鎖的線程節(jié)點(diǎn)。可以看做一個(gè)鏈表。

一:獨(dú)占鎖

獨(dú)占鎖的state只有0和1兩種情況(如果是可重入鎖也可以把state一直往上加,這里不討論),state = 1時(shí)說(shuō)明已經(jīng)有線程爭(zhēng)用到鎖。線程獲取鎖時(shí)一般是通過(guò)aqs的lock方法,如果state為0,首先嘗試cas修改state=1,成功返回,失敗時(shí)則加入阻塞隊(duì)列。 非公共鎖使用時(shí),線程節(jié)點(diǎn)加入阻塞隊(duì)列時(shí)依然會(huì)嘗試cas獲取鎖,最后如果還是失敗再老老實(shí)實(shí)阻塞在隊(duì)列中。

獨(dú)占鎖還可以分為公平鎖和非公平鎖,公平鎖要求鎖節(jié)點(diǎn)依據(jù)順序加入阻塞隊(duì)列,通過(guò)判斷前置節(jié)點(diǎn)的狀態(tài)來(lái)改變后置節(jié)點(diǎn)的狀態(tài),比如前置節(jié)點(diǎn)獲取鎖后,釋放鎖時(shí)會(huì)通知后置節(jié)點(diǎn)。

非公平鎖則不一定會(huì)按照隊(duì)列的節(jié)點(diǎn)順序來(lái)獲取鎖,如上面所說(shuō),會(huì)先嘗試cas操作,失敗再進(jìn)入阻塞隊(duì)列。

二:共享鎖

共享鎖的state狀態(tài)可以是0到n。共享鎖維護(hù)的阻塞隊(duì)列和互斥鎖不太一樣,互斥鎖的節(jié)點(diǎn)釋放鎖后只會(huì)通知后置節(jié)點(diǎn),而共享鎖獲取鎖后會(huì)通知所有的共享類(lèi)型節(jié)點(diǎn),讓他們都來(lái)獲取鎖。共享鎖用于countdownlatch工具類(lèi)與cyliderbarrier等,可以很好地完成多線程的協(xié)調(diào)工作

鎖Lock和Conditon

Lock 鎖維護(hù)這兩個(gè)內(nèi)部類(lèi)fairsync和unfairsync,都繼承自aqs,重寫(xiě)了部分方法,實(shí)際上大部分方法還是aqs中的,Lock只是重新把AQS做了封裝,讓程序員更方便地使用Lock鎖。

和Lock鎖搭配使用的還有condition,由于Lock鎖只維護(hù)著一個(gè)阻塞隊(duì)列,有時(shí)候想分不同情況進(jìn)行鎖阻塞和鎖通知怎么辦,原來(lái)我們一般會(huì)使用多個(gè)鎖對(duì)象,現(xiàn)在可以使用condition來(lái)完成這件事,比如線程A和線程B分別等待事件A和事件B,可以使用兩個(gè)condition分別維護(hù)兩個(gè)隊(duì)列,A放在A隊(duì)列,B放在B隊(duì)列,由于Lock和condition是綁定使用的,當(dāng)事件A觸發(fā),線程A被喚醒,此時(shí)他會(huì)加入Lock自己的CLH隊(duì)列中進(jìn)行鎖爭(zhēng)用,當(dāng)然也分為公平鎖和非公平鎖兩種,和上面的描述一樣。

Lock和condtion的組合廣泛用于JUC包中,比如生產(chǎn)者和消費(fèi)者模型,再比如cyliderbarrier。

讀寫(xiě)鎖

讀寫(xiě)鎖也是Lock的一個(gè)子類(lèi),它在一個(gè)阻塞隊(duì)列中同時(shí)存儲(chǔ)讀線程節(jié)點(diǎn)和寫(xiě)線程節(jié)點(diǎn),讀寫(xiě)鎖采用state的高16位和低16位分別代表獨(dú)占鎖和共享鎖的狀態(tài),如果共享鎖的state > 0可以繼續(xù)獲取讀鎖,并且state-1,如果=0,則加入到阻塞隊(duì)列中,寫(xiě)鎖節(jié)點(diǎn)和獨(dú)占鎖的處理一樣,因此一個(gè)隊(duì)列中會(huì)有兩種類(lèi)型的節(jié)點(diǎn),喚醒讀鎖節(jié)點(diǎn)時(shí)不會(huì)喚醒寫(xiě)鎖節(jié)點(diǎn),喚醒寫(xiě)鎖節(jié)點(diǎn)時(shí),則會(huì)喚醒后續(xù)的節(jié)點(diǎn)。

因此讀寫(xiě)鎖一般用于讀多寫(xiě)少的場(chǎng)景,寫(xiě)鎖可以降級(jí)為讀鎖,就是在獲取到寫(xiě)鎖的情況下可以再獲取讀鎖。

并發(fā)工具類(lèi)

1 countdownlatch

countdownlatch主要通過(guò)AQS的共享模式實(shí)現(xiàn),初始時(shí)設(shè)置state為N,N是countdownlatch初始化使用的size,每當(dāng)有一個(gè)線程執(zhí)行countdown,則state-1,state = 0之前所有線程阻塞在隊(duì)列中,當(dāng)state=0時(shí)喚醒隊(duì)頭節(jié)點(diǎn),隊(duì)頭節(jié)點(diǎn)依次通知所有共享類(lèi)型的節(jié)點(diǎn),喚醒這些線程并執(zhí)行后面的代碼。

2 cycliderbarrier

cycliderbarrier主要通過(guò)lock和condition結(jié)合實(shí)現(xiàn),首先設(shè)置state為屏障等待的線程數(shù),在某個(gè)節(jié)點(diǎn)設(shè)置一個(gè)屏障,所有線程運(yùn)行到此處會(huì)阻塞等待,其實(shí)就是等待在一個(gè)condition的隊(duì)列中,并且每當(dāng)有一個(gè)線程到達(dá),state -=1 則當(dāng)所有線程到達(dá)時(shí),state = 0,則喚醒condition隊(duì)列的所有結(jié)點(diǎn),去執(zhí)行后面的代碼。

3 samphere

samphere也是使用AQS的共享模式實(shí)現(xiàn)的,與countlatch大同小異,不再贅述。

4 exchanger

exchanger就比較復(fù)雜了。使用exchanger時(shí)會(huì)開(kāi)辟一段空間用來(lái)讓兩個(gè)線程進(jìn)行交互操作,這個(gè)空間一般是一個(gè)棧或隊(duì)列,一個(gè)線程進(jìn)來(lái)時(shí)先把數(shù)據(jù)放到這個(gè)格子里,然后阻塞等待其他線程跟他交換,如果另一個(gè)線程也進(jìn)來(lái)了,就會(huì)讀取這個(gè)數(shù)據(jù),并把自己的數(shù)據(jù)放到對(duì)方線程的格子里,然后雙雙離開(kāi)。當(dāng)然使用棧和隊(duì)列的交互是不同的,使用棧的話匹配的是最晚進(jìn)來(lái)的一個(gè)線程,隊(duì)列則相反。

原子數(shù)據(jù)類(lèi)型

原子數(shù)據(jù)類(lèi)型基本都是通過(guò)cas操作實(shí)現(xiàn)的,避免并發(fā)操作時(shí)出現(xiàn)的安全問(wèn)題。

同步容器

同步容器主要就是concurrenthashmap了,在集合類(lèi)中我已經(jīng)講了chm了,所以在這里簡(jiǎn)單帶過(guò),chm1.7通過(guò)分段鎖來(lái)實(shí)現(xiàn)鎖粗化,使用的死LLock鎖,而1.8則改用synchronized和cas的結(jié)合,性能更好一些。

還有就是concurrentlinkedlist,ConcurrentSkipListMap與CopyOnWriteArrayList。

第一個(gè)鏈表也是通過(guò)cas和synchronized實(shí)現(xiàn)。

而concurrentskiplistmap則是一個(gè)跳表,跳表分為很多層,每層都是一個(gè)鏈表,每個(gè)節(jié)點(diǎn)可以有向下和向右兩個(gè)指針,先通過(guò)向右指針進(jìn)行索引,再通過(guò)向下指針細(xì)化搜索,這個(gè)的搜索效率是很高的,可以達(dá)到logn,并且它的實(shí)現(xiàn)難度也比較低。通過(guò)跳表存map就是把entry節(jié)點(diǎn)放在鏈表中了。查詢時(shí)按照跳表的查詢規(guī)則即可。

CopyOnWriteArrayList是一個(gè)寫(xiě)時(shí)復(fù)制鏈表,查詢時(shí)不加鎖,而修改時(shí)則會(huì)復(fù)制一個(gè)新list進(jìn)行操作,然后再賦值給原list即可。 適合讀多寫(xiě)少的場(chǎng)景。

阻塞隊(duì)列

BlockingQueue 實(shí)現(xiàn)之 ArrayBlockingQueue

  1. ArrayBlockingQueue其實(shí)就是數(shù)組實(shí)現(xiàn)的阻塞隊(duì)列,該阻塞隊(duì)列通過(guò)一個(gè)lock和兩個(gè)condition實(shí)現(xiàn),一個(gè)condition負(fù)責(zé)從隊(duì)頭插入節(jié)點(diǎn),一個(gè)condition負(fù)責(zé)隊(duì)尾讀取節(jié)點(diǎn),通過(guò)這樣的方式可以實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模型。

BlockingQueue 實(shí)現(xiàn)之 LinkedBlockingQueue

<pre>

  1. LinkedBlockingQueue是用鏈表實(shí)現(xiàn)的阻塞隊(duì)列,和arrayblockqueue有所區(qū)別,它支持實(shí)現(xiàn)為***隊(duì)列,并且它使用兩個(gè)lock和對(duì)應(yīng)的condition搭配使用,這是因?yàn)殒湵砜梢酝瑫r(shí)對(duì)頭部和尾部進(jìn)行操作,而數(shù)組進(jìn)行操作后可能還要執(zhí)行移位和擴(kuò)容等操作。

  2. 所以鏈表實(shí)現(xiàn)更靈活,讀寫(xiě)分別用兩把鎖,效率更高。

BlockingQueue 實(shí)現(xiàn)之 SynchronousQueue

  1. SynchronousQueue實(shí)現(xiàn)是一個(gè)不存儲(chǔ)數(shù)據(jù)的隊(duì)列,只會(huì)保留一個(gè)隊(duì)列用于保存線程節(jié)點(diǎn)。詳細(xì)請(qǐng)參加上面的exchanger實(shí)現(xiàn)類(lèi),它就是基于SynchronousQueue設(shè)計(jì)出來(lái)的工具類(lèi)。

BlockingQueue 實(shí)現(xiàn)之 PriorityBlockingQueue

PriorityBlockingQueue

  1. PriorityBlockingQueue是一個(gè)支持優(yōu)先級(jí)的***隊(duì)列。默認(rèn)情況下元素采取自然順序排列,也可以通過(guò)比較器comparator來(lái)指定元素的排序規(guī)則。元素按照升序排列。

DelayQueue

  1. DelayQueue是一個(gè)支持延時(shí)獲取元素的***阻塞隊(duì)列。隊(duì)列使用PriorityQueue來(lái)實(shí)現(xiàn)。隊(duì)列中的元素必須實(shí)現(xiàn)Delayed接口,在創(chuàng)建元素時(shí)可以指定多久才能從隊(duì)列中獲取當(dāng)前元素。只有在延遲期滿時(shí)才能從隊(duì)列中提取元素。我們可以將DelayQueue運(yùn)用在以下應(yīng)用場(chǎng)景:

  2. 緩存系統(tǒng)的設(shè)計(jì):可以用DelayQueue保存緩存元素的有效期,使用一個(gè)線程循環(huán)查詢DelayQueue,一旦能從DelayQueue中獲取元素時(shí),表示緩存有效期到了。

  3. 定時(shí)任務(wù)調(diào)度。使用DelayQueue保存當(dāng)天將會(huì)執(zhí)行的任務(wù)和執(zhí)行時(shí)間,一旦從DelayQueue中獲取到任務(wù)就開(kāi)始執(zhí)行,從比如TimerQueue就是使用DelayQueue實(shí)現(xiàn)的。

線程池

類(lèi)圖

首先看看executor接口,只提供一個(gè)run方法,而他的一個(gè)子接口executorservice則提供了更多方法,比如提交任務(wù),結(jié)束線程池等。

然后抽象類(lèi)abstractexecutorservice提供了更多的實(shí)現(xiàn)了,最后我們最常使用的類(lèi)ThreadPoolExecutor就是繼承它來(lái)的。

ThreadPoolExecutor可以傳入多種參數(shù)來(lái)自定義實(shí)現(xiàn)線程池。

而我們也可以使用Executors中的工廠方法來(lái)實(shí)例化常用的線程池。

常用線程池

比如newFixedThreadPool

newSingleThreadExecutor newCachedThreadPool

newScheduledThreadPool等等,這些線程池即可以使用submit提交有返回結(jié)果的callable和futuretask任務(wù),通過(guò)一個(gè)future來(lái)接收結(jié)果,或者通過(guò)callable中的回調(diào)函數(shù)call來(lái)回寫(xiě)執(zhí)行結(jié)果。也可以用execute執(zhí)行無(wú)返回值的runable任務(wù)。

在探討這些線程池的區(qū)別之前,先看看線程池的幾個(gè)核心概念。

1 任務(wù)隊(duì)列:線程池中維護(hù)了一個(gè)任務(wù)隊(duì)列,每當(dāng)向線程池提交任務(wù)時(shí),任務(wù)加入隊(duì)列。

2 工作線程:也叫worker,從線程池中獲取任務(wù)并執(zhí)行,執(zhí)行后被回收或者保留,因情況而定。

3 核心線程數(shù)和大線程數(shù),核心線程數(shù)是線程池需要保持存活的線程數(shù)量,以便接收任務(wù),大線程數(shù)是能創(chuàng)建的線程數(shù)上限。

4 newFixedThreadPool可以設(shè)置固定的核心線程數(shù)和大線程數(shù),一個(gè)任務(wù)進(jìn)來(lái)以后,就會(huì)開(kāi)啟一個(gè)線程去執(zhí)行,并且這部分線程不會(huì)被回收,當(dāng)開(kāi)啟的線程達(dá)到核心線程數(shù)時(shí),則把任務(wù)先放進(jìn)任務(wù)隊(duì)列。當(dāng)任務(wù)隊(duì)列已滿時(shí),才會(huì)繼續(xù)開(kāi)啟線程去處理,如果線程總數(shù)打到大線程數(shù)限制,任務(wù)隊(duì)列又是滿的時(shí)候,會(huì)執(zhí)行對(duì)應(yīng)的拒絕策略。

5 拒絕策略一般有幾種常用的,比如丟棄任務(wù),丟棄隊(duì)尾任務(wù),回退給調(diào)用者執(zhí)行,或者拋出異常,也可以使用自定義的拒絕策略。

6 newSingleThreadExecutor是一個(gè)單線程執(zhí)行的線程池,只會(huì)維護(hù)一個(gè)線程,他也有任務(wù)隊(duì)列,當(dāng)任務(wù)隊(duì)列已滿并且線程數(shù)已經(jīng)是1個(gè)的時(shí)候,再提交任務(wù)就會(huì)執(zhí)行拒絕策略。

7 newCachedThreadPool比較特別,第一個(gè)任務(wù)進(jìn)來(lái)時(shí)會(huì)開(kāi)啟一個(gè)線程,而后如果線程還沒(méi)執(zhí)行完前面的任務(wù)又有新任務(wù)進(jìn)來(lái),就會(huì)再創(chuàng)建一個(gè)線程,這個(gè)線程池使用的是無(wú)容量的SynchronousQueue隊(duì)列,要求請(qǐng)求線程和接受線程匹配時(shí)才會(huì)完成任務(wù)執(zhí)行。 所以如果一直提交任務(wù),而接受線程來(lái)不及處理的話,就會(huì)導(dǎo)致線程池不斷創(chuàng)建線程,導(dǎo)致cpu消耗很大。

8 ScheduledThreadPoolExecutor內(nèi)部使用的是delayqueue隊(duì)列,內(nèi)部是一個(gè)優(yōu)先級(jí)隊(duì)列priorityqueue,也就是一個(gè)堆。通過(guò)這個(gè)delayqueue可以知道線程調(diào)度的先后順序和執(zhí)行時(shí)間點(diǎn)。

Fork/Join框架

又稱(chēng)工作竊取線程池。

我們?cè)诖髮W(xué)算法課本上,學(xué)過(guò)的一種基本算法就是:分治。其基本思路就是:把一個(gè)大的任務(wù)分成若干個(gè)子任務(wù),這些子任務(wù)分別計(jì)算,最后再M(fèi)erge出最終結(jié)果。這個(gè)過(guò)程通常都會(huì)用到遞歸。

而Fork/Join其實(shí)就是一種利用多線程來(lái)實(shí)現(xiàn)“分治算法”的并行框架。

另外一方面,可以把Fori/Join看作一個(gè)單機(jī)版的Map/Reduce,只不過(guò)這里的并行不是多臺(tái)機(jī)器并行計(jì)算,而是多個(gè)線程并行計(jì)算。

1 與ThreadPool的區(qū)別 通過(guò)上面例子,我們可以看出,它在使用上,和ThreadPool有共同的地方,也有區(qū)別點(diǎn): (1) ThreadPool只有“外部任務(wù)”,也就是調(diào)用者放到隊(duì)列里的任務(wù)。 ForkJoinPool有“外部任務(wù)”,還有“內(nèi)部任務(wù)”,也就是任務(wù)自身在執(zhí)行過(guò)程中,分裂出”子任務(wù)“,遞歸,再次放入隊(duì)列。 (2)ForkJoinPool里面的任務(wù)通常有2類(lèi),RecusiveAction/RecusiveTask,這2個(gè)都是繼承自FutureTask。在使用的時(shí)候,重寫(xiě)其compute算法。

2 工作竊取算法 上面提到,F(xiàn)orkJoinPool里有”外部任務(wù)“,也有“內(nèi)部任務(wù)”。其中外部任務(wù),是放在ForkJoinPool的全局隊(duì)列里面,而每個(gè)Worker線程,也有一個(gè)自己的隊(duì)列,用于存放內(nèi)部任務(wù)。

3 竊取的基本思路就是:當(dāng)worker自己的任務(wù)隊(duì)列里面沒(méi)有任務(wù)時(shí),就去scan別的線程的隊(duì)列,把別人的任務(wù)拿過(guò)來(lái)執(zhí)行

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專(zhuān)為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

網(wǎng)站題目:如何才能夠系統(tǒng)地學(xué)習(xí)Java并發(fā)技術(shù)?-創(chuàng)新互聯(lián)
轉(zhuǎn)載源于:http://www.rwnh.cn/article2/hdcic.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站維護(hù)動(dòng)態(tài)網(wǎng)站、電子商務(wù)定制開(kāi)發(fā)、網(wǎng)站收錄建站公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司
呈贡县| 郑州市| 吉安县| 珲春市| 博湖县| 汶川县| 淳安县| 宜章县| 师宗县| 福鼎市| 嵊泗县| 清苑县| 行唐县| 吴忠市| 松潘县| 西平县| 东光县| 新巴尔虎右旗| 泗洪县| 栖霞市| 盐山县| 凤翔县| 和林格尔县| 咸阳市| 松潘县| 灵武市| 新昌县| 宁乡县| 甘德县| 彭州市| 保山市| 青海省| 丹巴县| 枞阳县| 金坛市| 潼关县| 元江| 南昌市| 西乌| 丽江市| 竹北市|