RSS订阅欢迎来到Java程序员学习天地!
你的位置:首页 » JAVA » 正文

HashMap和HashTable线程安全性解析

选择字号: 超大 标准 发布时间:2017年05月22日 | 作者:amour505 | 0个评论 | 604人浏览

     HashMap和HashTable的区别是面试官比较喜欢问的问题,今天我整理了下这两个对象的一些原理解析:

首先我们先说说hashmap和hashtable的区别:两者最主要的区别为hashtable是线程安全而hashmap是非线程安全的,那么问题来了,为什么hashmap是非线程安全的呢?想必很多人都不了解,让我们先来了解一下HashMap的底层存储结构,HashMap底层是一个Entry数组,一旦发生Hash冲突的的时候,HashMap采用拉链法解决碰撞冲突,Entry内部的变量:

final Object key; 

Object value;

Entry next;

int hash;

   hashmap的put方法:

public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value); //null总是放在数组的第一个链表中
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        //遍历链表
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            //如果key在链表中已存在,则替换为新value
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }
        modCount++;
        addEntry(hash, key, value, i);
        return null;

    }

 

void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<K,V>(hash, key, value, e); //参数e, 是Entry.next
    //如果size超过threshold,则扩充table大小。再散列
    if (size++ >= threshold)
            resize(2 * table.length);

}

put方法是非同步的,其中put方法调用了addEntry方法,该方法同样不是同步的,另外我们知道在HashMap存在扩容的情况,对应的方法为HashMap中的resize方法:

    

 void resize(int newCapacity) {
        Entry[] oldTable = table;
        int oldCapacity = oldTable.length;
        if (oldCapacity == MAXIMUM_CAPACITY) {
            threshold = Integer.MAX_VALUE;
            return;
        }
        Entry[] newTable = new Entry[newCapacity];
        transfer(newTable);
        table = newTable;
        threshold = (int)(newCapacity * loadFactor);

    }

void transfer(Entry[] newTable) {
        Entry[] src = table;
        int newCapacity = newTable.length;
        for (int j = 0; j < src.length; j++) {
            Entry<K,V> e = src[j];
            if (e != null) {
                src[j] = null;
                do {
                    Entry<K,V> next = e.next;
                    //重新计算index
                    int i = indexFor(e.hash, newCapacity);
                    e.next = newTable[i];
                    newTable[i] = e;
                    e = next;
                } while (e != null);
            }
        }

    }

     resize方法不是同步的,可以看到扩容方法也不是同步的,通过代码我们知道在扩容过程中,会调用transfer方法新生成一个新的容量的数组,然后对原数组的所有键值对重新进行计算和写入新的数组,之后指向新生成的数组,该方法同样不是同步的

    那么hashtable如何实现线程安全的呢,Hashtable 继承于Dictionary,实现了Map、Cloneable、Java.io.Serializable接口。
Hashtable 的函数都是同步的,这意味着它是线程安全的。它的key、value都不可以为null。此外,Hashtable中的映射不是有序的。

Hashtable的构造函数

// 默认构造函数。public Hashtable() 

// 指定“容量大小”的构造函数public Hashtable(int initialCapacity) 

// 指定“容量大小”和“加载因子”的构造函数public Hashtable(int initialCapacity, float loadFactor) 

// 包含“子Map”的构造函数public Hashtable(Map<? extends K, ? extends V> t)


Hashtable的API


synchronized void                clear()
synchronized Object              clone()            
 boolean             contains(Object value)
 synchronized boolean             containsKey(Object key)
 synchronized boolean             containsValue(Object value)
 synchronized Enumeration<V>      elements()
 synchronized Set<Entry<K, V>>    entrySet()
 synchronized boolean             equals(Object object)
 synchronized V                   get(Object key)
 synchronized int                 hashCode()
 synchronized boolean             isEmpty()
 synchronized Set<K>              keySet()
 synchronized Enumeration<K>      keys()
 synchronized V                   put(K key, V value)
 synchronized void                putAll(Map<? extends K, ? extends V> map)
 synchronized V                   remove(Object key)
 synchronized int                 size()
 synchronized String              toString()
 synchronized Collection<V>       values()

通过hashtable api可以看出,具体实现代码可以百度hashtable原理,所有的方法都是同步的,因此hashtable是线程安全的。

标签:Java基础

额 本文暂时没人评论 来添加一个吧

发表评论

必填

选填

选填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

控制面板
您好,欢迎到访网站!
随机文章
热门文章
热评文章
最近发表