成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何線程安全的使用 HashMap

開發(fā) 前端
Collections.synchronizedMap 方法使用了裝飾器模式為線程不安全的 HashMap 提供了一個線程安全的裝飾器類 SynchronizedMap。

這篇文章,我們聊聊線程安全使用 HashMap 的四種技巧。

圖片圖片

1.方法內(nèi)部:每個線程創(chuàng)建單獨的 HashMap

如下圖,tomcat 接收到到請求后,依次調(diào)用控制器 Controller、服務(wù)層 Service 、數(shù)據(jù)庫訪問層的相關(guān)方法。

每次訪問服務(wù)層方法 serviceMethod 時,都會在方法體內(nèi)部創(chuàng)建一個單獨的 HashMap ,  將相關(guān)請求參數(shù)拷貝到 HashMap 里,然后調(diào)用 DAO 方法進行數(shù)據(jù)庫操作。

圖片圖片

每個 HTTP 處理線程在服務(wù)層方法體內(nèi)部都有自己的 HashMap 實例,在多線程環(huán)境下,不需要對 HashMap 進行任何同步操作。

這也是我們使用最普遍也最安全的的方式,是 CRUD 最基本的操作。

2.配置數(shù)據(jù):初始化單線程寫,后續(xù)只提供讀

系統(tǒng)啟動之后,我們可以將配置數(shù)據(jù)加載到本地緩存 HashMap 里 ,這些配置信息初始化之后,就不需要寫入了,后續(xù)只提供讀操作。

圖片圖片

上圖中顯示一個非常簡單的配置類 SimpleConfig ,內(nèi)部有一個 HashMap 對象 configMap 。構(gòu)造函數(shù)調(diào)用初始化方法,初始化方法內(nèi)部的邏輯是:將配置數(shù)據(jù)存儲到 HashMap 中。

SimpleConfig 類對外暴露了 getConfig 方法 ,當(dāng) main 線程初始化 SimpleConfig 對象之后,當(dāng)其他線程調(diào)用  getConfig 方法時,因為只有讀,沒有寫操作,所以是線程安全的。

3.讀寫鎖:讀讀不互斥,讀寫互斥,寫寫互斥

讀寫鎖是一把鎖分為兩部分:讀鎖和寫鎖,其中讀鎖允許多個線程同時獲得,而寫鎖則是互斥鎖。

它的規(guī)則是:讀讀不互斥,讀寫互斥,寫寫互斥,適用于讀多寫少的業(yè)務(wù)場景。

我們一般都使用 ReentrantReadWriteLock ,該類實現(xiàn)了 ReadWriteLock 。ReadWriteLock 接口也很簡單,其內(nèi)部主要提供了兩個方法,分別返回讀鎖和寫鎖 。

public interface ReadWriteLock {
    //獲取讀鎖
    Lock readLock();
    //獲取寫鎖
    Lock writeLock();
}

讀寫鎖的使用方式如下所示:

  1. 創(chuàng)建 ReentrantReadWriteLock 對象 , 當(dāng)使用 ReadWriteLock 的時候,并不是直接使用,而是獲得其內(nèi)部的讀鎖和寫鎖,然后分別調(diào)用 lock / unlock 方法 ;
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  1. 讀取共享數(shù)據(jù) ;
Lock readLock = readWriteLock.readLock();
readLock.lock();
try {
   // TODO 查詢共享數(shù)據(jù)
} finally {
   readLock.unlock();
}
  1. 寫入共享數(shù)據(jù);
Lock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
   // TODO 修改共享數(shù)據(jù)
} finally {
   writeLock.unlock();
}

下面的代碼展示如何使用 ReadWriteLock 線程安全的使用 HashMap :

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockCache {
  
    // 創(chuàng)建一個 HashMap 來存儲緩存的數(shù)據(jù)
    private Map<String, String> map = new HashMap<>();

    // 創(chuàng)建讀寫鎖對象
    private ReadWriteLock rw = new ReentrantReadWriteLock();

    // 放對象方法:向緩存中添加一個鍵值對
    public void put(String key, String value) {
        // 獲取寫鎖,以確保當(dāng)前操作是獨占的
        rw.writeLock().lock();
        try {
            // 執(zhí)行寫操作,將鍵值對放入 map
            map.put(key, value);
        } finally {
            // 釋放寫鎖
            rw.writeLock().unlock();
        }
    }

    // 取對象方法:從緩存中獲取一個值
    public String get(String key) {
        // 獲取讀鎖,允許并發(fā)讀操作
        rw.readLock().lock();
        try {
            // 執(zhí)行讀操作,從 map 中獲取值
            return map.get(key);
        } finally {
            // 釋放讀鎖
            rw.readLock().unlock();
        }
    }
}

使用讀寫鎖操作 HashMap 是一個非常經(jīng)典的技巧,消息中間件 RockeMQ NameServer (名字服務(wù))保存和查詢路由信息都是通過這種技巧實現(xiàn)的。

另外,讀寫鎖可以操作多個 HashMap ,相比 ConcurrentHashMap 而言,ReadWriteLock 可以控制緩存對象的顆粒度,具備更大的靈活性。

4.Collections.synchronizedMap : 讀寫均加鎖

如下代碼,當(dāng)我們多線程使用 userMap 時,

static Map<Long, User> userMap = Collections.synchronizedMap(new HashMap<Long, User>());

進入 synchronizedMap 方法:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
       return new SynchronizedMap<>(m);
}

圖片圖片

SynchronizedMap 內(nèi)部包含一個對象鎖 Object mutex ,它本質(zhì)上是一個包裝類,將 HashMap 的讀寫操作重新實現(xiàn)了一次,我們看到每次讀寫時,都會用 synchronized 關(guān)鍵字來保證操作的線程安全。

雖然 Collections.synchronizedMap 這種技巧使用起來非常簡單,但是我們需要理解它的每次讀寫都會加鎖,性能并不會特別好。

5.總結(jié)

這篇文章,筆者總結(jié)了四種線程安全的使用 HashMap 的技巧。

1)方法內(nèi)部:每個線程創(chuàng)建單獨的 HashMap

這是我們使用最普遍,也是非??煽康姆绞健C總€線程在方法體內(nèi)部創(chuàng)建HashMap 實例,在多線程環(huán)境下,不需要對 HashMap 進行任何同步操作。

2) 配置數(shù)據(jù):初始化單線程寫,后續(xù)只提供讀

中間件在啟動時,會讀取配置文件,將配置數(shù)據(jù)寫入到 HashMap 中,主線程寫完之后,以后不會再有寫入操作,其他的線程可以讀取,不會產(chǎn)生線程安全問題。

3)讀寫鎖:讀讀不互斥,讀寫互斥,寫寫互斥

讀寫鎖是一把鎖分為兩部分:讀鎖和寫鎖,其中讀鎖允許多個線程同時獲得,而寫鎖則是互斥鎖。

它的規(guī)則是:讀讀不互斥,讀寫互斥,寫寫互斥,適用于讀多寫少的業(yè)務(wù)場景。

使用讀寫鎖操作 HashMap 是一個非常經(jīng)典的技巧,消息中間件 RockeMQ NameServer (名字服務(wù))保存和查詢路由信息都是通過這種技巧實現(xiàn)的。

4)Collections.synchronizedMap  : 讀寫均加鎖

Collections.synchronizedMap 方法使用了裝飾器模式為線程不安全的 HashMap 提供了一個線程安全的裝飾器類 SynchronizedMap。

通過 SynchronizedMap 來間接的保證對 HashMap 的操作是線程安全,而 SynchronizedMap 底層也是通過 synchronized 關(guān)鍵字來保證操作的線程安全。

責(zé)任編輯:武曉燕 來源: 勇哥Java實戰(zhàn)
相關(guān)推薦

2023-03-21 09:07:38

HashMap線程安全

2020-04-22 20:35:02

HashMap線程安全

2024-03-22 12:29:03

HashMap線程

2024-05-20 13:13:01

線程安全Java

2023-01-26 02:07:51

HashSet線程安全

2024-06-17 00:02:00

線程安全HashMapJDK 1.7

2019-01-28 08:50:09

線程安全

2021-02-19 10:40:48

HashMap線程Java

2025-01-07 12:43:14

2017-07-06 15:36:56

線程線程安全開發(fā)

2025-01-21 00:00:00

HashMap死循環(huán)數(shù)據(jù)損壞

2017-09-18 09:03:36

線程安全單例

2020-09-25 08:49:42

HashMap

2009-05-22 15:10:13

2012-04-16 10:12:54

Java線程

2014-03-25 10:09:46

2017-09-18 09:17:07

線程安全單例

2011-05-25 13:17:22

MySQL

2013-01-28 09:13:46

2023-10-23 20:03:02

Go緩存
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产九九av | 久久久青草 | 精品不卡| 九色在线视频 | 91亚洲国产成人久久精品网站 | 一区二区三区视频在线免费观看 | h肉视频| 一区二区在线 | 国产大片黄色 | 91在线网站 | 九九综合 | 毛片免费观看 | 一区二区三区国产好 | 欧美国产日韩在线观看 | 99精品欧美一区二区三区综合在线 | 特级丰满少妇一级aaaa爱毛片 | 国产成人精品一区二区三区在线 | 欧美综合一区 | 欧美激情精品久久久久久变态 | 欧美日韩成人影院 | 精品久久电影 | 99视频入口| 国产欧美视频一区二区三区 | 国产精品一区二区免费 | 久久在线免费 | 另类视频在线 | 国产精品99久久久久久大便 | 国产一区二区免费 | 亚洲一区中文字幕 | 亚洲 成人 在线 | 欧美一区二区久久 | 在线国产小视频 | 999久久久久久久久6666 | 欧美日本亚洲 | 夜夜久久 | 中文字幕一级 | 亚洲日本激情 | 日韩av手机在线观看 | 在线中文字幕亚洲 | 精品视频一区二区 | av国产精品 |