5同步工具類

同步容器類

常見同步類

  1. Vector

  2. Hashtable

  3. Collections.synchronizedXxx工廠方法創(chuàng)建的封裝容器

    注:Vector和Hashtable是早期JDK的部分在塔,Collections.synchronizedXxx是JDK1.2添加的

同步容器實現(xiàn)線程安全的方式

  • 使用自身的鎖來保護它的每個方法
  • 將他們的狀態(tài)封裝起來,并對每個公有方法都進行同步湃窍,使得每次只有一個線程能訪問容器的狀態(tài)

同步容器類的問題

  • 容器上的復合操作存在線程安全問題

  • 常見的復合操作:

    1. 迭代(反復訪問元素,直到遍歷完容器內(nèi)的所有元素)
    2. 跳轉(zhuǎn)(根據(jù)指定順序找到當前元素的下一個元素)
    3. 條件運算(例如:若沒有則添加)
    //查詢vector.size()狀態(tài)可能是失效的
    for(int i=0; i<vector.size(); i++) {
        doSomething(vector.get(8));
    }
    
      ```
      /**
       * 先檢查后查詢的復合操作
       */
      public static Object getLast(Vector list) {
          //查詢list.size()的狀態(tài)可能是失效的
          int lastIndex = list.size() - 1;
          return list.get(lastIndex);
      }
      ```
    

解決復合操作線程不安全的方法

  • 客戶端在復合操作上加鎖(同步容器使用自身的鎖來保護它的每個方法)
sychronized(vector) {
    for(int i=0; i<vector.size(); i++) {
        doSomething(vector.get(8));
    }   
}
public static Object getLast(Vector list) {
    synchronized(list) {
        int lastIndex = list.size() - 1;
    return list.get(lastIndex);   
    }
}

迭代器與ConcurrentModificationException

  • 容器迭代的方式

    1. 直接使用Iterator
    2. 使用Java5.0引入的for-each
  • 迭代器的問題

    • 在同步容器的迭代器是并沒有考慮到并發(fā)修改的問題,并且他們表現(xiàn)出的行為是“及時失敗(fail-fast)”漫拭,這意味著碳锈,當他們發(fā)現(xiàn)容器在迭代過程中被修改時,就會拋出一個ConcurrentModificationException異常
    • 這種“及時失敗”的迭代器并不是一種完備的處理機制召夹,而只是“善意地”捕獲并發(fā)錯誤岩喷,因此只能作為并發(fā)問題的預警指示
  • 解決ConcurrentModificationException問題

    • “克隆”容器,并在副本上進行迭代

      注:克隆過程中仍然需要對容器加鎖监憎;克隆容器時存在顯著的性能開銷纱意;這種方式的好壞取決于多個因素,包括容器大小鲸阔,在每個元素上執(zhí)行的工作偷霉,迭代操作相對于容器其他操作的調(diào)用頻率迄委,以及在響應時間和吞吐量等方面的需求

  • 常見隱藏的迭代

    1. 容器的hashCode和equals方法會間接執(zhí)行迭代操作,當容器作為另一個容器的元素或鍵時就會出現(xiàn)這種情況

    2. containsAll类少、removeAll和retainAll等方法

    3. 將容器作為參數(shù)的構(gòu)造函數(shù)

      注:所有間接的迭代操作都可能拋出ConcurrentModificationException

并發(fā)容器

ConcurrentHashMap與Hashtable的區(qū)別

  • 相同點:都是線程安全的容器
  • 不同點
    1. 同步方式不同:前者分段同步且讀取操作不同步叙身,并發(fā)性能高;后者全表同步硫狞,并發(fā)性能低
    2. 內(nèi)存消耗:前者占用內(nèi)存大信轿,因為分段,內(nèi)部容器較多或占用更多額外內(nèi)存
    3. 迭代器一致性:前者迭代器具有弱一致性妓忍,因為讀取非同步虏两,所以讀取的結(jié)果只包含創(chuàng)建迭代器時已有的元素;后者因為是全表同步世剖,所以保證了迭代器的強一致性
    4. 增加API:前者增加了一些對常見復合操作的支持定罢,例如“若沒有則添加”、替換以及有條件刪除
    5. 弱化API:前者弱化了size()旁瘫、isEmpty()方法的語義以反映容器的并發(fā)性祖凫,這些方法的結(jié)果可能是失效的
    6. 迭代異常:迭代時不會出現(xiàn)ConcurrentModificationException,后者會出現(xiàn)異常
  • 并發(fā)容器替代同步容器
    • ConcurrentHashMap <- HashTable酬凳、Collections.synchronizedMap(Map)
    • ConcurrentSkipListMap <- Collections.synchronizedMap(TreeMap)
    • ConcurrentSkipListSet <- Collections.synchronizedSet(TreeSet)

CopyOnWriteArrayList特點

  1. 寫操作復制內(nèi)部容器惠况,讀操作讀取的是內(nèi)部容器副本,迭代時不會出現(xiàn)ConcurrentModificationException
  2. 適合于讀操作多宁仔,寫操作少的多線程環(huán)境

中斷

概念

  • 中斷是一種用于取消線程操作的協(xié)作機制稠屠;一個線程不能強制其他線程停止正在執(zhí)行的操作而去執(zhí)行其他的操作,但是要求(通知)其他線程執(zhí)行到某個可以暫停的地方停止正在執(zhí)行的操作翎苫,前提是別的線程愿意停止當前的操作

中斷方法介紹

  1. isInterruputed 對象方法权埠,獲取線程的中斷狀態(tài)

    注:線程死了后,該方法始終返回false

  2. interrupt 對象方法煎谍,設(shè)置線程的中斷狀態(tài)

    注:如果線程阻塞在Object的wait方法或Thread的join攘蔽、sleep方法上,調(diào)用此方法將清除被阻塞線程的中斷狀態(tài)呐粘,并且調(diào)用這些方法的地方將收到一個InterruptException

  3. interrupted 靜態(tài)方法满俗,返回當前線程的中斷狀態(tài),并清除中斷狀態(tài)作岖、

    注:線程死了后唆垃,該方法始終返回false

中斷異常InterruptedException處理

  • 傳遞InterruptException:不捕獲該異常,或者捕獲該異常然后在執(zhí)行某種簡單的清理工作后再次拋出這個異常
  • 恢復中斷:有時候不能拋出InterruptException鳍咱,例如當代碼是Runnable的一部分時降盹,這種情況下必須捕獲InterruptException,并通過調(diào)用當前線程的interrupt方法恢復中斷狀態(tài)谤辜,將中斷信息告知調(diào)用棧中更高層的代碼

同步工具類

概念

  • 同步工具類可以是任何對象蓄坏,只要他根據(jù)其自身狀態(tài)來協(xié)調(diào)線程的控制流;例如阻塞隊列可以作為同步工具類

常用同步工具類

  1. CountDownLatch(閉鎖)
    • 延遲線程的進度丑念,直到其達到終止狀態(tài)涡戳,所有線程將釋放進度,當其到達結(jié)束狀態(tài)后脯倚,將不會再改變狀態(tài)
  2. FutureTask(也可以當做閉鎖)
    • 可以返回計算結(jié)果的任務(wù)
    • 包括三種狀態(tài):等待運行(Waiting to run)渔彰、正在運行(Running)、運行完成(Completed)
    • 執(zhí)行完成表示計算的所有結(jié)束方式:正常結(jié)束推正、由與取消結(jié)束恍涂、由與異常結(jié)束;任務(wù)進入完成狀態(tài)后將會停止在這個狀態(tài)上
    • FutureTask表示的計算通過Callable接口來實現(xiàn)
      • Callable可以拋出受檢查的或未受檢查的異常植榕,并且任何代碼都可能拋出Error
      • 無論任務(wù)代碼拋出什么異常再沧,都會被封裝到一個ExecutionException中,并在Future.get中被重新拋出
      • 上面兩條將使get代碼變得復雜尊残,因為不僅需要處理可能出現(xiàn)的ExecutionException以及未受檢查的CancellationException炒瘸,而且還由于ExecutionException是做為一個Throwable類返回的
    • 優(yōu)點:提前啟動計算,可以減少等待結(jié)果需要的時間
  3. Semaphore
    • 對資源施加邊界
  4. CyclicBarrier
    • 與閉鎖相同點:柵欄類似于閉鎖寝衫,他能阻塞一組線程直到某個事件發(fā)生
    • 與閉鎖不同點:閉鎖是一次性的顷扩,柵欄可多次使用;閉鎖用于等待事件慰毅,而柵欄用于等待其他線程
  5. Exchanger
    • 它是一種Two-Party柵欄隘截,各方在柵欄位置上交換數(shù)據(jù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市汹胃,隨后出現(xiàn)的幾起案子婶芭,更是在濱河造成了極大的恐慌,老刑警劉巖统台,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件雕擂,死亡現(xiàn)場離奇詭異,居然都是意外死亡贱勃,警方通過查閱死者的電腦和手機井赌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贵扰,“玉大人仇穗,你說我怎么就攤上這事∑萑疲” “怎么了纹坐?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長舞丛。 經(jīng)常有香客問我耘子,道長果漾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任谷誓,我火速辦了婚禮绒障,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捍歪。我一直安慰自己户辱,他們只是感情好,可當我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布糙臼。 她就那樣靜靜地躺著庐镐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪变逃。 梳的紋絲不亂的頭發(fā)上必逆,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機與錄音韧献,去河邊找鬼末患。 笑死,一個胖子當著我的面吹牛锤窑,可吹牛的內(nèi)容都是我干的璧针。 我是一名探鬼主播,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼渊啰,長吁一口氣:“原來是場噩夢啊……” “哼探橱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绘证,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤隧膏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后嚷那,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胞枕,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年魏宽,在試婚紗的時候發(fā)現(xiàn)自己被綠了腐泻。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡队询,死狀恐怖派桩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蚌斩,我是刑警寧澤铆惑,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響员魏,放射性物質(zhì)發(fā)生泄漏丑蛤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一逆趋、第九天 我趴在偏房一處隱蔽的房頂上張望盏阶。 院中可真熱鬧晒奕,春花似錦闻书、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至闷袒,卻和暖如春坑律,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背囊骤。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工晃择, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人也物。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓宫屠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親滑蚯。 傳聞我的和親對象是個殘疾皇子浪蹂,可洞房花燭夜當晚...
    茶點故事閱讀 45,440評論 2 359

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

  • 并發(fā)與多線程是每個人程序員都頭疼的內(nèi)容,幸好Java庫所提供了豐富并發(fā)基礎(chǔ)模塊告材,這些多線程安全的模塊作為并發(fā)工具類...
    登高且賦閱讀 1,229評論 0 8
  • 每一個想學習Java多線程的人坤次,手里至少有這本書或者至少要看這本書。強烈建議大家多看幾遍斥赋。 代碼中比較容易出現(xiàn)bu...
    玥玥籽閱讀 945評論 0 0
  • 本文是我自己在秋招復習時的讀書筆記缰猴,整理的知識點,也是為了防止忘記疤剑,尊重勞動成果滑绒,轉(zhuǎn)載注明出處哦!如果你也喜歡骚露,那...
    波波波先森閱讀 11,273評論 4 56
  • 如果你在亞馬遜搜索java相關(guān)的書蹬挤,本書排名是非常靠前的棘幸,豆瓣的評分也很高焰扳。剛好我最近忙找工作,也需要復習并發(fā)相關(guān)...
    whiledoing閱讀 4,514評論 1 6
  • 睡眼惺忪。早六點半響了十分鐘的鬧鐘自己壓根沒聽到吨悍,等到乒乓的又一首生活奏鳴曲不斷侵擾耳膜終于將我喚起時扫茅,時間已經(jīng)是...
    yangzhian閱讀 217評論 0 0