码迷,mamicode.com
首页 > 其他好文 > 详细

自定义CopyOnWriteHashMap

时间:2018-02-27 17:40:40      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:数据   extends   city   replace   version   系统设计   rem   线程   post   

    在系统设计的过程中经常使用本地缓存(ConcurrentHashMap实现),由于ConcurrentHashMap的特性,可以保证线程安全。通常缓存中的数据往往是读多写少的,ConcurrentHashMap是完完全全线程安全类,虽然相比较HashTable做了降低锁粒度的优化,但对于读请求是没有必要加锁。Doug Lea大神在设计concurrent包的时候为我们提供了一个CopyOnWriteArrayList,这个类通过读写分离的方式来实现线程安全,即读请求不加锁,写请求才加锁(典型的空间换时间实现)。这对于缓存来说是个很好的容器,不过很可惜JDK并未提供CopyOnWriteMap。这里自己简单模仿写了一个,希望在今后能有所帮助,类的实现如下:

package com.bj58.jyfz.fortunecheck.util;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author zhangyining on 18/2/27 027.
 */
public class CopyOnWriteHashMap<K,V> extends HashMap<K,V> {

    private static final long serialVersionUID = 5209276986986262310L;

    /**
     * lock
     */
    final transient ReentrantLock lock = new ReentrantLock();

    /**
     * internal collection
     */
    private transient volatile HashMap<K,V> map;

    /**
     * init capacity
     */
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

    public CopyOnWriteHashMap() {
        setMap(new HashMap<K,V>(DEFAULT_INITIAL_CAPACITY));
    }

    public CopyOnWriteHashMap(HashMap<? extends K, ? extends V> m) {
        HashMap<K,V> map = new HashMap<>(m);
        setMap(map);
    }

    final HashMap<K,V> getMap() {
        return map;
    }

    final void setMap(HashMap<K,V> map) {
        this.map = map;
    }

    @Override
    public int size() {
        return this.map.size();
    }

    @Override
    public boolean isEmpty() {
        return size() == 0;
    }

    @Override
    public boolean containsKey(Object key) {
        return this.map.containsKey(key);
    }

    @Override
    public void clear() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            HashMap<K,V> newMap = new HashMap<>(map);
            newMap.clear();
            map = newMap;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean containsValue(Object value) {
        return map.containsValue(value);
    }

    @Override
    public Set<K> keySet() {
        return map.keySet();
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        return map.entrySet();
    }

    @Override
    public Collection<V> values() {
        return map.values();
    }

    @Override
    public V replace(K key, V value) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            HashMap<K,V> newMap = new HashMap<>(map);
            V val = newMap.replace(key, value);
            map = newMap;
            return val;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean replace(K key, V oldValue, V newValue) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            HashMap<K,V> newMap = new HashMap<>(map);
            boolean flag = newMap.replace(key, oldValue, newValue);
            map = newMap;
            return flag;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public V put(K key, V value) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            HashMap<K,V> newMap = new HashMap<>(map);
            V val = newMap.put(key, value);
            map = newMap;
            return val;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            HashMap<K,V> newMap = new HashMap<>(map);
            newMap.putAll(m);
            map = newMap;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public V get(Object key) {
        return map.get(key);
    }

    @Override
    public V remove(Object key) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            HashMap<K,V> newMap = new HashMap<>(map);
            V val = newMap.remove(key);
            map = newMap;
            return val;
        } finally {
            lock.unlock();
        }
    }
}

这里面只重写了几个常用的方法,后续大家可以自行添加!这里强调一点,由于读请求不加锁,所以会有可能读取到脏数据,此情况发生在读写并发高的情况,通常都是毫秒级别的误差,对于缓存来说可以忽略了!

自定义CopyOnWriteHashMap

标签:数据   extends   city   replace   version   系统设计   rem   线程   post   

原文地址:https://www.cnblogs.com/1ning/p/8479680.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!