日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

并发编程-10线程安全策略之不可变对象

發布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 并发编程-10线程安全策略之不可变对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 腦圖
  • 四個線程安全策略
  • 不可變對象定義
  • 不可變對象需要滿足的條件
  • 如何創建不可變對象
  • 使用final關鍵字定義不可變對象
    • 修飾變量示例
      • final修飾基本數據類型及String: 初始化之后不能修改 (線程安全)
      • final修飾引用類型變量:初始化之后不能再修改其引用,但可以修改值 (線程不安全)
  • 使用JDK / Guava中提供的工具類創建不可變對象
    • Collections.unmodifiableXXX 示例 (線程安全)
    • Guava ImmutableXXX 示例 (線程安全)
  • 代碼

腦圖


四個線程安全策略

線程限制

一個被線程限制的對象,由線程獨占,并且只能被占有它的線程修改

共享只讀

一個共享只讀的對象,在沒有額外同步的情況下,可以被多個線程并發訪問,但是任何線程都不能修改它

線程安全對象

一個線程安全的對象或者容器,在內部通過同步機制來保證線程安全,所以其他線程無需額外的同步就可以通過公共接口隨意訪問它

被守護對象

被守護對象只能通過獲取特定的鎖來訪問


不可變對象定義

在Java中,有一種對象發布了就是安全的,被稱之為不可變對象。

不可變對象可以在多線程中可以保證線程安全


不可變對象需要滿足的條件

  • 對象創建以后其狀態就不能修改
  • 對象所有域都是final類型
  • 對象是正確創建的(在對象創建期間,this引用沒有逸出)


如何創建不可變對象

  • 類聲明成final類型,使其不可以被繼承

  • 所有的成員設置成私有的,使其他的類和對象不能直接訪問這些成員

  • 對變量不提供set方法

  • 所有可變的成員聲明為final,這樣只能對他們賦值一次

  • 通過構造器初始化所有成員,進行深度拷貝

  • get方法中,不直接返回對象本身,而是克隆對象,返回對象的拷貝

提到不可變的對象就不得不說一下final關鍵字,該關鍵字可以修飾類、方法、變量:


使用final關鍵字定義不可變對象

final關鍵字可以修飾類、方法、變量

  • 修飾類:不能被繼承(final類中的所有方法都會被隱式的聲明為final方法)
  • 修飾方法:

1、鎖定方法不被繼承類修改;
2、可提升效率(private方法被隱式修飾為final方法)

  • 修飾變量:

基本數據類型變量: 初始化之后不能修改
引用類型變量: 初始化之后不能再修改其引用

  • 修飾方法參數:同修飾變量

修飾變量示例

final修飾基本數據類型及String: 初始化之后不能修改 (線程安全)

可知:編譯報錯,被final修飾后,基本類型和String的變量無法被修改


final修飾引用類型變量:初始化之后不能再修改其引用,但可以修改值 (線程不安全)

package com.artisan.example.immutable;import java.util.ArrayList; import java.util.List; import java.util.Map;import com.google.common.collect.Maps;import lombok.extern.slf4j.Slf4j;@Slf4j public class FinalDemo {// 基本數據類型 int 使用final修飾 驗證被final修飾的基本數據類型無法改變private final static int num = 1;// String類型 使用final修飾 驗證被final修飾的基本數據類型無法改變private final static String name = "小工匠";// 引用類型 初始化之后不能再修改其引用,但是可修改其中值private final static Map<String, Object> map = Maps.newHashMap();static {map.put("name", "artisan");map.put("age", 20);map.put("sex", "男");}public static void main(String[] args) {// 被final修飾的基本數據類型和String無法改變// 編譯報錯: The final field FinalDemo.num cannot be assigned// num = 2;// 編譯報錯: The final field FinalDemo.name cannot be assigned// name = "artisan";// 引用對象,此引用無法指向別的對象,但可修改該對象的值map.put("name", "小工匠");log.info("name:{}", map.get("name"));// 驗證 方法參數被final修飾的情況List<String> list = new ArrayList<>();list.add("我是小工匠");test2(list);}// final修飾傳遞進來的變量基本類型,不可別改變private void test(final int a) {// 不能修改// 編譯報錯: The final local variable a cannot be assigned. It must be blank and not using a compound assignment// a = 2;log.info("a:{}", a);}// final修飾方法傳遞進來的變量 引用對象,無法指向別的對象,但可修改該對象的值private static void test2(final List<String> list) {// 添加數據list.add("我是artisan");list.forEach(str ->{log.info("數據:{}",str);});}}

輸出:

需要我們注意的是,final修飾引用類型時,雖然不能將引用再指向別的對象,但可修改該對象的值。 線程不安全


使用JDK / Guava中提供的工具類創建不可變對象

除了final可以定義不可變對象,java提供的Collections類,也可定義不可變對象。

  • JDK中的 Collections.unmodifiableXXX傳入的對象一經初始化便無法修改,XXX可表示Collection、List、Set、Map等

  • 谷歌的Guava中的ImmutableXXX,XXX同樣可表示Collection、List、Set、Map等


Collections.unmodifiableXXX 示例 (線程安全)

執行后結果如下:

由此可見,用Collections.UnmodifiableMap修飾的對象是不可修改的,如果嘗試修改對象的值,在程序運行時會拋出異常。


跟下Collections.UnmodifiableMap的源碼

繼續看下UnmodifiableMap

主要是將一個新的集合的所有更新方法變為拋出異常


Guava ImmutableXXX 示例 (線程安全)

package com.artisan.example.immutable;import com.artisan.anno.ThreadSafe; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet;@ThreadSafe public class GuavaImmutableSetDemo {// 使用Guava中提供的類來定義不可變對象的集合// 不可變listprivate final static ImmutableList<Integer> list = ImmutableList.of(1, 2, 3);// 不可變的setprivate final static ImmutableSet<Integer> set = ImmutableSet.copyOf(list);// 不可變的map,需要以k/v的形式傳入數據,即奇數位參數為key,偶數位參數為valueprivate final static ImmutableMap<String, String> map = ImmutableMap.of("k1", "v1", "k2","v2");// 通過builder調用鏈的方式構造不可變的mapprivate final static ImmutableMap<String, String> map2 = ImmutableMap.<String, String>builder().put("key1", "value1").put("key2", "value2").put("key3", "value3").build();public static void main(String[] args) {// 修改對象內的數據就會拋出UnsupportedOperationException異常// 不能添加新的元素 ,運行將拋出 java.lang.UnsupportedOperationExceptionlist.add(4);// 不能添加新的元素 ,運行將拋出 java.lang.UnsupportedOperationExceptionset.add(4);// 不能添加新的元素 ,運行將拋出 java.lang.UnsupportedOperationExceptionmap.put("k3", "v3");// 不能添加新的元素 ,運行將拋出 java.lang.UnsupportedOperationExceptionmap2.put("key4", "value4");} }

上述代碼是線程安全的,開發時如果我們的對象可以變為不可變對象,我們盡量將對象變為不可變對象,這樣可以避免線程安全問題。


代碼

https://github.com/yangshangwei/ConcurrencyMaster

總結

以上是生活随笔為你收集整理的并发编程-10线程安全策略之不可变对象的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产激情网址 | 久草影视在线观看 | 色爱综合区 | 无法忍受在线观看 | 日韩精品在线观看一区 | 欧美日韩视频无码一区二区三 | 日韩精品一区二区三区视频 | 国产精品久久久久久久久久久久久久久久 | 亚洲AV无码成人精品区麻豆 | 性v天堂| 国产h在线观看 | 男生和女生靠逼视频 | 超碰97成人 | www插插插 | 日韩欧美久久久 | 精品久久久久久久久久久久久久久久久 | 国产ts系列| 中文字幕av一区二区三区人妻少妇 | 无码h肉动漫在线观看 | a在线天堂 | 欧美日韩一区二区综合 | 五月婷激情 | 伊人久久伊人 | 亚洲精品视频在线看 | va毛片| 91亚洲国产成人精品性色 | 中文字幕在线观看三区 | 深夜在线网站 | 亚洲va中文字幕 | 国产一区二区三区在线观看视频 | 国产一二三在线视频 | 欧美老肥妇做爰bbww | 青青啪啪 | 日剧再来一次第十集 | 国产主播av在线 | av在线资源观看 | 日本久久综合 | 伊人久久一区二区三区 | 99re在线视频播放 | 国产精品国产馆在线真实露脸 | 2017日日夜夜| 无码人妻精品一区二区三区不卡 | 国产77777| 影音先锋婷婷 | 国产综合亚洲精品一区二 | 91免费看.| 超碰人人草 | 久草欧美视频 | 黄色网址网站 | 99视频+国产日韩欧美 | 色com| 欧美第一页浮力影院 | 国产欧美精品一区 | 涩涩视频在线观看免费 | 精品无码久久久久久久久成人 | 日韩a级大片| 国产女人18毛片水真多1 | 日本高清免费不卡视频 | 在线污视频 | 国产三级按摩推拿按摩 | 人人看人人做 | 国产污片在线观看 | 黄免费在线观看 | 五月天婷婷基地 | 黄页视频在线观看 | 亚洲gay视频 | 少妇做爰k8经典 | 国产稀缺真实呦乱在线 | 青青伊人影院 | 1024你懂的日韩 | 国产 日韩 欧美 制服丝袜 | 国产欧美综合一区 | free性欧美69巨大 | 天堂在线中文在线 | 午夜久久久久久久久久 | 少妇被躁爽到高潮 | 毛片1000部免费看 | 国产性生活片 | 国产日韩一区二区三免费高清 | 精品少妇一区二区三区免费观看 | 国产第一草草影院 | 黄色av网址在线 | 丰满岳跪趴高撅肥臀尤物在线观看 | jizz日本视频 | 秋霞伦理一区二区 | 色翁荡息又大又硬又粗又爽 | 国产99久久久国产精品 | 成人黄色a级片 | 国内精品久久久久 | 色香蕉av| 精品自拍第一页 | 91人妻一区二区三区 | 射射射综合网 | 在线观看福利片 | 性久久久久久久久 | 国产精品久免费的黄网站 | 黄色xxxxx | 国产精品久久久久精 | 国产一区二区在线免费观看 |