同步容器并發(fā)容器

同步容器類

  • Vector嗦随、Hashtable,及由Collections.synchronizedXxx等工程方法創(chuàng)建的類。
  • 這些類實現(xiàn)線程安全方式是:將它們的狀態(tài)封裝起來,并對每個公有方法都進行同步婉支,使得每次只有一個線程能方法容器狀態(tài)。

同步容器類的問題

  • 客戶端新建的復(fù)合操作需要通過容器類的鎖來保證原子性澜建。
  • 在迭代操作中向挖,多線程情況下回出現(xiàn)ArrayIndexOutOfBoundsException異常,如果要解決炕舵,則需要在客戶端加鎖何之,但是犧牲了一些伸縮性。

迭代器與CncurrrentModificationException

  • 發(fā)現(xiàn)容器在迭代過程中被修改過咽筋,會拋出CME異常溶推。實現(xiàn)原理:將容器計數(shù)器與容器關(guān)聯(lián)起來:如果在迭代期間計數(shù)器被修改,那么hasNext或next將拋出CME異常。然后悼潭,這種檢查在沒有同步的情況下進行的庇忌,因此可能看到失效的計數(shù)值:ABA問題舞箍。

隱藏的迭代器

  • 容器的toString舰褪、hashCode、equals疏橄、containsAll占拍、removeAll、retainAll以及包容器作為參數(shù)的構(gòu)造函數(shù)都會對容器進行迭代捎迫,在并發(fā)下就可能出現(xiàn)CME異常晃酒。所以在并發(fā)情況下,在迭代期間需要對容器加鎖窄绒。

并發(fā)容器

  • 并發(fā)容器為了改變同步容器的性能贝次,同步容器對容器狀態(tài)的訪問時串行化,以實現(xiàn)線程安全彰导,這種方法降低了并發(fā)性蛔翅,和吞吐量。
  • 并發(fā)容器針對多線程并發(fā)訪問設(shè)計的位谋,如果需要提高并發(fā)性使用以下替代方案山析。
  • ConcurrentHashMap代替同步且散列的Map.
  • CopyOnWriteArrayList用于在遍歷操作為主要操作的情況下代替同步的List。
  • ConcurrentMap接口中增加了常見復(fù)合操作的支持:“若沒有則添加”掏父、替換笋轨、有條件刪除。
  • ConcurrentSkipListMap代替SortedMap
  • ConcurrentSkipListSet代替SortedSet
    *并發(fā)容器類提供的迭代器不會拋出CME異常赊淑。

Queue爵政、BlockingQueue容器接口

  • Queue用來臨時保存一組待處理元素,實現(xiàn)類包括:ConcurrentLinkedQueue(先進先出隊列)陶缺、PriorityQueue(優(yōu)先隊列茂卦,非并發(fā))
  • Queue上的操作不會阻塞,如果隊列為空,返回空值组哩。
  • Queue通過LinkedList來實現(xiàn)的等龙。
  • BlockingQueue擴展Queue,增加了可阻塞的插入和獲取等操作,如果隊列為空伶贰,那么獲取元素操作將一直阻塞蛛砰,直到隊列中出現(xiàn)一個可用元素。插入時黍衙,如果隊列已滿(對于有界隊列來說泥畅,無界隊列除外),插入操作將一直阻塞琅翻,知道隊列中出現(xiàn)可用空間位仁。適合“生產(chǎn)者-消費者模式”
  • BlockingQueue提供了offer方法柑贞,當隊列滿時offer添加元素失敗返回false,此時可以做相應(yīng)策略調(diào)整(減少生產(chǎn)線程或序列化數(shù)據(jù)到磁盤)聂抢,同樣也提供了poll方法钧嘶,在一定時間內(nèi)如果沒有獲取到元素則返回null。

ConcurrentHashMap

  • 使用分段鎖(Lock Striping)來提高并發(fā)性和伸縮性琳疏。
  • size和isEmpty返回的結(jié)果可能會過期有决,實際上他只是一個估值,但這兩個方法用的不多空盼。
  • 在CHM中沒有實現(xiàn)對Map加鎖以提供獨占方法书幕,在Hashtable、synchronizedMap中獲得Map的鎖能防止其他線程訪問這個Map
  • 與Hashtable揽趾、synchronizedMap相比台汇,CHM有更多優(yōu)勢,大多數(shù)情況下使用CHM來提高代碼的伸縮性篱瞎,只有當程序需要加鎖Map以進行獨占訪問苟呐,或者需要依賴同步Map帶來的一些其他作用是才應(yīng)該放棄CHM.

CopyOnWriteArrayList、CopyOnWriteArraySet

  • 寫入時復(fù)制容器奔缠,在修改的時候會創(chuàng)建并發(fā)布一個新的容器副本掠抬。
  • 修改方法(刪除、添加)是加鎖的校哎,避免多個線程調(diào)用產(chǎn)生多個副本两波。
  • 修改時會復(fù)制底層數(shù)組,所以需要一定開銷闷哆,所以適合讀遠大于寫的業(yè)務(wù)場景腰奋。
    Java并發(fā)編程:并發(fā)容器之CopyOnWriteArrayList(轉(zhuǎn)載)

阻塞隊列和生產(chǎn)者-消費者模式

  • BlockingQueue的多種實現(xiàn):LinkedBlockingQueue、ArrayBlockingQueue是FIFO隊列抱怔。PriorityBlockingQueue是按優(yōu)先級排序隊列劣坊,即可根據(jù)元組自然排序來比較元素(如果他們實現(xiàn)Comparable方法),也可以使用Comparator來比較屈留。

雙端隊列

  • Deque(發(fā)音“deck”)和BlockingDeque對Queue局冰、BlockingQueue進行了擴展。Deque是一個雙端隊列灌危,實現(xiàn)了在隊列頭和尾高效插入和移除康二。
  • 實現(xiàn)為ArrayDeque、LinkedBlockingQueue

阻塞方法與中斷方法

  • 阻塞:等待I/O操作結(jié)束勇蝙、等待獲取一個鎖沫勿,等待從Thread.sleep方法中醒來、等待另一個線程的計算結(jié)果。阻塞線程處于阻塞狀態(tài)产雹,等待某個不受它控制的事件發(fā)生后才能繼續(xù)執(zhí)行诫惭,當外部事件發(fā)生時,線程被置回Runnable(就緒狀態(tài))蔓挖。

  • LinkedBlockingQueue的take夕土、put等方法會拋出InterruptedException與Thread.sleep一樣。當方法拋出InterruptedException異常时甚,表示該方法時一個阻塞方法隘弊,如果這個方法被中斷哈踱,那么它將努力提前結(jié)束阻塞狀態(tài)荒适。(只是努力不是保證)

  • LinkedBlockingQueue的take阻塞方法源碼

 /** Lock held by take, poll, etc */
    private final ReentrantLock takeLock = new ReentrantLock();

    /** Wait queue for waiting takes */
    private final Condition notEmpty = takeLock.newCondition();

public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();
        try {
            while (count.get() == 0) {
                notEmpty.await();
            }
            x = dequeue();
            c = count.getAndDecrement();
            if (c > 1)
                notEmpty.signal();
        } finally {
            takeLock.unlock();
        }
        if (c == capacity)
            signalNotFull();
        return x;
    }
  • 中斷,Thread類提供了interrupt方法开镣,用于中斷線程或者查詢線程是否已經(jīng)被中斷刀诬。每個線程都有一個布爾類型的屬性,標識線程的中斷狀態(tài)邪财,當中斷線程時將設(shè)置這個狀態(tài)陕壹。
  • 中斷是一種協(xié)作機制,一個線程不能強制其它線程停止正在執(zhí)行的操作而去執(zhí)行其它的操作树埠。
  • A線程中斷B時糠馆,A僅僅是要求B在執(zhí)行到某個可以暫停的地方停止正在執(zhí)行的動作---前提是如果線程B愿意停止下來。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怎憋,一起剝皮案震驚了整個濱河市又碌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌绊袋,老刑警劉巖毕匀,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異癌别,居然都是意外死亡皂岔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門展姐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來躁垛,“玉大人,你說我怎么就攤上這事圾笨〗坦荩” “怎么了?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵墅拭,是天一觀的道長活玲。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么舒憾? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任镀钓,我火速辦了婚禮,結(jié)果婚禮上镀迂,老公的妹妹穿的比我還像新娘丁溅。我一直安慰自己,他們只是感情好探遵,可當我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布窟赏。 她就那樣靜靜地躺著,像睡著了一般箱季。 火紅的嫁衣襯著肌膚如雪涯穷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天藏雏,我揣著相機與錄音拷况,去河邊找鬼。 笑死掘殴,一個胖子當著我的面吹牛赚瘦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奏寨,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼起意,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了病瞳?” 一聲冷哼從身側(cè)響起揽咕,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎仍源,沒想到半個月后心褐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡笼踩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年逗爹,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嚎于。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡掘而,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出于购,到底是詐尸還是另有隱情袍睡,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布肋僧,位于F島的核電站斑胜,受9級特大地震影響控淡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜止潘,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一掺炭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧凭戴,春花似錦涧狮、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至档痪,卻和暖如春涉枫,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钞它。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工拜银, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留殊鞭,地道東北人遭垛。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像操灿,于是被迫代替她去往敵國和親锯仪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,870評論 2 361

推薦閱讀更多精彩內(nèi)容