zoukankan      html  css  js  c++  java
  • Hashtable源码分析

    1、Hashtable是线程安全的,采用全量加锁的方式控制多线程并发访问

    2、不允许null键和null值(HashMap可以接受为null的键值(key)和值(value))

    3、一次仅能有一个对象来读取和修改Hashtable,每个线程要获取或修改都要先拿到同步锁,其他线程要等待同步锁被释放之后才能再次获取同步锁去读取和更新Hashtable

    构造方法:

    // 默认初始容量是11   
     public Hashtable() {
            this(11, 0.75f);
        }
    // 带参构造
        public Hashtable(int initialCapacity, float loadFactor) {
            if (initialCapacity < 0)
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            if (loadFactor <= 0 || Float.isNaN(loadFactor))
                throw new IllegalArgumentException("Illegal Load: "+loadFactor);
    
            if (initialCapacity==0)
                initialCapacity = 1;
            this.loadFactor = loadFactor;
          // 初始化哈希表
            table = new Entry<?,?>[initialCapacity];
          // 阀值为初始容量乘负载因子和Integer.MAX_VALUE - 7之间的最小者
            threshold = (int)Math.min(initialCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        }

    get方法,put方法,remove方法等对Hashtable进行读取和修改的方法都是同步方法,锁的是Hashtable对象,因此多线程共享一个hashtable对象时,同一时刻只有一个线程能读取和修改Hashtable

        @SuppressWarnings("unchecked")
        public synchronized V get(Object key) {
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % tab.length;
            for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
                if ((e.hash == hash) && e.key.equals(key)) {
                    return (V)e.value;
                }
            }
            return null;
        }
    
        public synchronized V put(K key, V value) {
            // Make sure the value is not null
            if (value == null) {
                throw new NullPointerException();
            }
    
            // Makes sure the key is not already in the hashtable.
            Entry<?,?> tab[] = table;
            int hash = key.hashCode();
            int index = (hash & 0x7FFFFFFF) % tab.length;
            @SuppressWarnings("unchecked")
            Entry<K,V> entry = (Entry<K,V>)tab[index];
            for(; entry != null ; entry = entry.next) {
                if ((entry.hash == hash) && entry.key.equals(key)) {
                    V old = entry.value;
                    entry.value = value;
                    return old;
                }
            }
    
            addEntry(hash, key, value, index);
            return null;
        }

    hashtable put数据时候可以get数据吗?
      多个线程共享一个hashtable对象时,一个get时,另一个不能put。
    成员方法中,synchronized锁住的是对象this,只有调用同一个对象的方法才需要获取锁。同时,同一个对象中所有加了synchronize的方法只能一次调 用一个,所以不能。
    静态方法中,synchronized锁的是整个类对象,类似于(X.class),该类中所有加了synchronized的静态方法,一次只能调用一个。

    验证:

    public class HashTable {
    
        private Map<String, String> map = new HashMap();
    
        public synchronized String get(String key) {
            System.out.println("get开始");
            String value = map.get(key);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("get结束");
            return value;
        }
    
        public synchronized String put(String key, String value) {
            System.out.println("put开始");
            String oldValue = map.put(key, value);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("put结束");
            return oldValue;
        }
    }
    
    public static void main(String[] args) {
            final HashTable hashTable = new HashTable();
            new Thread(new Runnable() {
    //            HashTable hashTable = new HashTable();
    
                @Override
                public void run() {
                    hashTable.get("name");
                }
            }).start();
            new Thread(new Runnable() {
    //            HashTable hashTable = new HashTable();
    
                @Override
                public void run() {
                    hashTable.put("name", "yangyongjie");
                }
            }).start();
        }
    
    get开始
    get结束
    put开始
    put结束
    可以看到不同的同步方法时顺序执行的。
  • 相关阅读:
    HBase with MapReduce (MultiTable Read)
    HBase with MapReduce (SummaryToFile)
    HBase with MapReduce (Summary)
    HBase with MapReduce (Read and Write)
    HBase with MapReduce (Only Read)
    Hbase中的BloomFilter(布隆过滤器)
    HBase的快照技术
    How To Use Hbase Bulk Loading
    Cloudera-Manager修改集群的IP
    Java中的HashSet和TreeSet
  • 原文地址:https://www.cnblogs.com/yangyongjie/p/10978833.html
Copyright © 2011-2022 走看看