国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java 隊列

Pocher / 2529人閱讀

摘要:隊列中有元素時,就說明有過期了,線程繼續(xù)執(zhí)行,然后元素出隊,根據(jù)相應(yīng)的移除緩存。所以嚴格來說,雖然實現(xiàn)了隊列接口,但是它的目的卻并不是隊列,而是將生產(chǎn)者消費者線程配對。轉(zhuǎn)移隊列鏈式轉(zhuǎn)移隊列。

引言

本周在編寫短信驗證碼頻率限制切面的時候,經(jīng)潘老師給的實現(xiàn)思路,使用隊列進行實現(xiàn)。

看了看java.util包下的Queue接口,發(fā)現(xiàn)還從來沒用過呢!

Collection集合類接口,由它派生出ListSetQueueMap屬于另一個獨立的接口,和Collection沒有繼承關(guān)系。

ListSetMap我們用的都是已經(jīng)相當熟練了,今天,我們就來學習這個隊列Queue

探索

隊列與棧都是數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)話題,隊列:先進先出;棧:后進先出。

方法

Queue接口中聲明了六個方法,分成三對來使用。

入隊操作

方法 特點 建議
add 入隊失敗拋出異常
offer 入隊失敗返回false 推薦

出隊操作

方法 特點 建議
remove 出隊失敗拋出異常
poll 出隊失敗返回null 推薦

取隊頭操作

方法 特點 建議
element 隊列為空時拋出異常
peek 隊列為空時返回null 推薦
PriorityQueue

java.util包中,除抽象類外,直接實現(xiàn)Queue接口的只有PriorityQueue優(yōu)先級隊列。

優(yōu)先級隊列比普通的隊列要高級,普通的隊列如果是先進的肯定是在隊頭的,而優(yōu)先級隊列根據(jù)優(yōu)先級判斷當前隊頭元素是什么。很適合實現(xiàn)操作系統(tǒng)中的按優(yōu)先級實現(xiàn)進程調(diào)度。

如果需要使用優(yōu)先級隊列進行排序時,需要傳入比較器。

該隊列使用數(shù)組實現(xiàn),線程不安全。

Deque

java.util包中,Deque接口繼承Queue接口。

Dequedouble-ended queue,雙端隊列。

雙端隊列,相比普通隊列就是可操作兩端,有兩個隊頭,也有兩個隊尾。

所以再去看Deque接口中聲明的方法,都是兩套的。offerFirstofferLastpollFirstpollLast等。

所以說,如果使用雙端隊列,不僅可以當隊列用,也可以當棧用,因為可以自己控制出的是隊頭還是隊尾。

Deque有兩個實現(xiàn)類:ArrayDequeLinkedList

原來LinkedList不僅實現(xiàn)了List接口,還實現(xiàn)了Deque接口。

兩者的區(qū)別顯而易見,一個是數(shù)組方式實現(xiàn)的,一個是鏈表的方式實現(xiàn)的。

BlockingQueue

這些都是java.util包下的,都是線程不安全的實現(xiàn),JDK所有線程安全的隊列實現(xiàn)都在java.util.concurrent包下,也就是阻塞隊列BlockingQueue

concurrent包下,自然是做了線程安全處理的了,在多線程環(huán)境下操作隊列需要使用。

生產(chǎn)者消費者

與阻塞隊列最密切的就是生產(chǎn)者消費者模型了,我們一起來探討一下。

生產(chǎn)者消費者模型,最初出現(xiàn)在操作系統(tǒng)中,多進程/多線程進行協(xié)作,完成同一任務(wù),必然需要相互合作與相互制約。

舉一個符合實際的例子,我想喝可樂。

可口可樂公司就是生產(chǎn)者,用于生產(chǎn)商品。

超市就相當于緩沖區(qū),用于存儲生產(chǎn)者生產(chǎn)出來的可樂,公司生產(chǎn)出可樂,然后放到超市里賣。

我就是消費者,去超市買可樂(消費過程)。

所以就會有一個同步的問題:

假設(shè)場景:超市能容量100瓶可樂。

所以,消費者去購買的前提是:超市內(nèi)有可樂,要不去了也買不著。

生產(chǎn)者生產(chǎn)的前提是:超市內(nèi)有空余位置,要不生產(chǎn)了往哪送呢?

類比到程序設(shè)計中,就是進程或線程之間的相互制約,也就是所謂的同步!

線程類比

一圖勝千言,我就不贅述了。

消費者線程想去找緩沖區(qū)要數(shù)據(jù),先判斷緩沖區(qū)內(nèi)有沒有數(shù)據(jù),如果沒有,消費者就拿不到,這個線程就等待,直到:緩沖區(qū)內(nèi)有數(shù)據(jù)。如果有,就從緩沖區(qū)將數(shù)據(jù)拿走。

生產(chǎn)者線程要去生產(chǎn)數(shù)據(jù),先判斷緩沖區(qū)內(nèi)有沒有空余位置,如果沒有,生產(chǎn)者就等待,直到:緩沖區(qū)內(nèi)有空位,如果有,就生產(chǎn)數(shù)據(jù),放入緩沖區(qū)。

阻塞隊列

阻塞隊列正適合生產(chǎn)者消費者模型,當隊列滿時,入隊操作就會被阻塞,當隊列空時,出隊操作就會被阻塞。

入隊出隊的offer方法和poll方法與原隊列接口的方法相比,多了時間的參數(shù)。當發(fā)生阻塞時,如果超過了設(shè)置的時間,線程就會退出,畢竟如果最壞的情況,一直不滿足條件,也不能一直阻塞下去。

boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
E poll(long timeout, TimeUnit unit) throws InterruptedException;
實現(xiàn)類

ArrayBlockingQueue:數(shù)組實現(xiàn)的阻塞隊列。

LinkedBlockingQueue:鏈表實現(xiàn)的阻塞隊列。

PriorityBlockingQueue:優(yōu)先級阻塞隊列。

雙向阻塞隊列

這個簡單,就是同時實現(xiàn)了BlockingQueueDeque接口。

java.util.concurrent包下只有一個雙向阻塞隊列的實現(xiàn):LinkedBlockingDeque

延時隊列

延時隊列:DelayQueue,看這個類名,無疑了,此隊列定與時間有關(guān)。

當一個元素入隊時,它并不是馬上進入隊列,而是根據(jù)設(shè)定的時間延時之后再入隊。

假設(shè)offer一個元素,設(shè)置時間為10s,在10s內(nèi)訪問隊列,是訪問不到元素的。

在延時之后,也就是10s之后,再去訪問,該元素才在隊列中。

使用場景

相關(guān)使用場景就是定時緩存。

HashMapDelayQueue配合使用。用DelayQueue來存儲緩存的key,如果隊列中有元素,表示該key就已經(jīng)過期。

然后再建一個線程去清理緩存,執(zhí)行到poll方法時,使用不傳時間的方法,如果隊列為空,該線程就一直阻塞在這,不往下走。

隊列中有元素時,就說明有key過期了,線程繼續(xù)執(zhí)行,然后元素出隊,根據(jù)相應(yīng)的key移除緩存。

細節(jié)

延時隊列中存儲的元素需要實現(xiàn)Delayed接口。

public interface Delayed extends Comparable {
    long getDelay(TimeUnit unit);
}

getDelay方法返回剩余的延時時間,如果返回值大于0,表示還未到入隊時間。

同步隊列

SynchronousQueue:同步隊列。

最好的解釋自然是官方文檔:A BlockingQueue in which each insert operation must wait for a corresponding remove operation by another thread, and vice versa.

這是一個阻塞隊列,它的特點是在執(zhí)行插入操作時必須等待另一個線程的移除操作。什么意思呢?

通俗的來說就是買可樂不需要去超市了,我(消費者)直接和廠家(生產(chǎn)者)購買。

所以,生產(chǎn)者和消費者同時存在時,這個交易才能執(zhí)行,兩方達成約定后,生產(chǎn)者生產(chǎn)可樂,賣給消費者。缺少任何一方另一方都會被阻塞,條件滿足時會喚醒對方繼續(xù)執(zhí)行,這就是所謂的同步。

代碼層面講就是:puttake方法都被調(diào)用的時候,兩者才開始執(zhí)行,并完成了數(shù)據(jù)的傳遞。

所以嚴格來說,雖然SynchronousQueue實現(xiàn)了隊列接口,但是它的目的卻并不是隊列,而是將生產(chǎn)者消費者線程配對。

轉(zhuǎn)移隊列

LinkedTransferQueue:鏈式轉(zhuǎn)移隊列。雖然放在了最后,但是查閱相關(guān)文檔發(fā)現(xiàn),實際的生產(chǎn)環(huán)境中,這個隊列最常用。

怎么轉(zhuǎn)移的呢?

消費者找隊列拿數(shù)據(jù),如果沒有數(shù)據(jù)可用,就設(shè)置一個標志位,表示我這里期待著一個數(shù)據(jù),然后消費者就開始等。

等著等著,直到生產(chǎn)者來了,判斷,如果有等著的,就直接把數(shù)據(jù)給它,實現(xiàn)了數(shù)據(jù)轉(zhuǎn)移。如果沒有呢?就去執(zhí)行數(shù)據(jù)入隊相關(guān)的操作。

總結(jié)

點開了阻塞隊列的源碼,發(fā)現(xiàn)線程安全是使用鎖實現(xiàn)的。

再看看面試問的東西:樂觀鎖、悲觀鎖、自旋鎖、偏向鎖、公平鎖,這都是寫啥東西呀?

吾生也有涯,而Java無涯。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/74322.html

相關(guān)文章

  • Java知識點總結(jié)(Java容器-Queue)

    摘要:知識點總結(jié)容器知識點總結(jié)容器接口與是在同一級別,都是繼承了接口。另一種隊列則是雙端隊列,支持在頭尾兩端插入和移除元素,主要包括。一個由鏈表結(jié)構(gòu)組成的無界阻塞隊列。是一個阻塞的線程安全的隊列,底層實現(xiàn)也是使用鏈式結(jié)構(gòu)。 Java知識點總結(jié)(Java容器-Queue) @(Java知識點總結(jié))[Java, Java容器] Queue Queue接口與List、Set是在同一級別,都是繼承了...

    hedzr 評論0 收藏0
  • [Java并發(fā)-6]“管程”-java管程初探

    摘要:語言在之前,提供的唯一的并發(fā)原語就是管程,而且之后提供的并發(fā)包,也是以管程技術(shù)為基礎(chǔ)的。但是管程更容易使用,所以選擇了管程。線程進入條件變量的等待隊列后,是允許其他線程進入管程的。并發(fā)編程里兩大核心問題互斥和同步,都可以由管程來幫你解決。 并發(fā)編程這個技術(shù)領(lǐng)域已經(jīng)發(fā)展了半個世紀了。有沒有一種核心技術(shù)可以很方便地解決我們的并發(fā)問題呢?這個問題, 我會選擇 Monitor(管程)技術(shù)。Ja...

    Steve_Wang_ 評論0 收藏0
  • 什么是阻塞隊列?如何使用阻塞隊列來實現(xiàn)生產(chǎn)者-消費者模型?

    摘要:什么是阻塞隊列阻塞隊列是一個在隊列基礎(chǔ)上又支持了兩個附加操作的隊列。阻塞隊列的應(yīng)用場景阻塞隊列常用于生產(chǎn)者和消費者的場景,生產(chǎn)者是向隊列里添加元素的線程,消費者是從隊列里取元素的線程。由鏈表結(jié)構(gòu)組成的無界阻塞隊列。 什么是阻塞隊列? 阻塞隊列是一個在隊列基礎(chǔ)上又支持了兩個附加操作的隊列。 2個附加操作: 支持阻塞的插入方法:隊列滿時,隊列會阻塞插入元素的線程,直到隊列不滿。 支持阻塞的...

    jemygraw 評論0 收藏0
  • java 隊列

    摘要:是基于鏈接節(jié)點的線程安全的隊列。通過這些高效并且線程安全的隊列類,為我們快速搭建高質(zhì)量的多線程程序帶來極大的便利。隊列內(nèi)部僅允許容納一個元素。該隊列的頭部是延遲期滿后保存時間最長的元素。 隊列簡述 Queue: 基本上,一個隊列就是一個先入先出(FIFO)的數(shù)據(jù)結(jié)構(gòu)Queue接口與List、Set同一級別,都是繼承了Collection接口。LinkedList實現(xiàn)了Deque接 口。...

    goji 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<