并发容器 一:容器的概览 二:集合历史 三:ConcurrentHashMap

并发容器
一:容器的概览
二:集合历史
三:ConcurrentHashMap

1.大纲

  集合类的历史

  ConcurrentHashMap

  CopyConWriteArrayList  

  并发队列

  

1.概览

  ConcurrentHashMap:线程安全的HashMap  

  CopyOnWriteArrayList:线程安全的List

  BlockingQueue:这是一个接口,表示阻塞队列

  ConcurrentLinkedQueue:高效的非阻塞并发队列,线程安全的,可以看做一个线程安全的LinkedList

  ConcurrentSkipListMap:是一个map,使用跳表数据结构进行快速查找

二:集合历史

1.vector与Hashtable

  vector:

package com.jun.juc.collections;

import java.util.Vector;

public class VectorDemo {
    public static void main(String[] args) {
        Vector vector = new Vector();
        vector.add("test");
        System.out.println(vector.get(0));
    }
}

  看一下get方法

    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }

  结论:

  这个是在方法上加了锁,继续看其他的方法,发现也是在方法是加的锁。

  Hashtable:

public class HashtableDemo {
    public static void main(String[] args) {
        Hashtable<String, String> stringStringHashtable = new Hashtable<>();
        stringStringHashtable.put("aa", "1111");
        System.out.println(stringStringHashtable.get("aa"));
    }
}

  看一下对应的get方法:

    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;
    }

  结论

  也是在方法上加的锁进行实现的

2.ArrayList与HashMap  

  是线程不安全的,可以使用如下的方法使得安全:

  Collections.synchronizedList(new ArrayList<>())

  Collections.synchronizedMap(new HashMap<>())

示例:

package com.jun.juc.collections;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SynchronizedListAndMap {
    public static void main(String[] args) {
        List<String> strList = Collections.synchronizedList(new ArrayList<String>());
        strList.add("tom");
    }
}

  进入:

    public static <T> List<T> synchronizedList(List<T> list) {
        return (list instanceof RandomAccess ?
                new SynchronizedRandomAccessList<>(list) :
                new SynchronizedList<>(list));
    }

  这个时候,看一下ArrayList:

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

  所以,走第一个对象,然后再进去看:

    /**
     * @serial include
     */
    static class SynchronizedRandomAccessList<E>
        extends SynchronizedList<E>
        implements RandomAccess {

        SynchronizedRandomAccessList(List<E> list) {
            super(list);
        }

  看父类:

    /**
     * @serial include
     */
    static class SynchronizedList<E>
        extends SynchronizedCollection<E>
        implements List<E> {
        private static final long serialVersionUID = -7754090372962971524L;

        final List<E> list;

        SynchronizedList(List<E> list) {
            super(list);
            this.list = list;
        }
        SynchronizedList(List<E> list, Object mutex) {
            super(list, mutex);
            this.list = list;
        }

        public boolean equals(Object o) {
            if (this == o)
                return true;
            synchronized (mutex) {return list.equals(o);}
        }
        public int hashCode() {
            synchronized (mutex) {return list.hashCode();}
        }

        public E get(int index) {
            synchronized (mutex) {return list.get(index);}
        }
        public E set(int index, E element) {
            synchronized (mutex) {return list.set(index, element);}
        }
        public void add(int index, E element) {
            synchronized (mutex) {list.add(index, element);}
        }
        public E remove(int index) {
            synchronized (mutex) {return list.remove(index);}
        }

        public int indexOf(Object o) {
            synchronized (mutex) {return list.indexOf(o);}
        }
        public int lastIndexOf(Object o) {
            synchronized (mutex) {return list.lastIndexOf(o);}
        }

        public boolean addAll(int index, Collection<? extends E> c) {
            synchronized (mutex) {return list.addAll(index, c);}
        }

        public ListIterator<E> listIterator() {
            return list.listIterator(); // Must be manually synched by user
        }

        public ListIterator<E> listIterator(int index) {
            return list.listIterator(index); // Must be manually synched by user
        }

        public List<E> subList(int fromIndex, int toIndex) {
            synchronized (mutex) {
                return new SynchronizedList<>(list.subList(fromIndex, toIndex),
                                            mutex);
            }
        }

        @Override
        public void replaceAll(UnaryOperator<E> operator) {
            synchronized (mutex) {list.replaceAll(operator);}
        }
        @Override
        public void sort(Comparator<? super E> c) {
            synchronized (mutex) {list.sort(c);}
        }

        /**
         * SynchronizedRandomAccessList instances are serialized as
         * SynchronizedList instances to allow them to be deserialized
         * in pre-1.4 JREs (which do not have SynchronizedRandomAccessList).
         * This method inverts the transformation.  As a beneficial
         * side-effect, it also grafts the RandomAccess marker onto
         * SynchronizedList instances that were serialized in pre-1.4 JREs.
         *
         * Note: Unfortunately, SynchronizedRandomAccessList instances
         * serialized in 1.4.1 and deserialized in 1.4 will become
         * SynchronizedList instances, as this method was missing in 1.4.
         */
        private Object readResolve() {
            return (list instanceof RandomAccess
                    ? new SynchronizedRandomAccessList<>(list)
                    : this);
        }
    }

  结论:

  发现是使用代码块的方式进行的安全。

三:ConcurrentHashMap

1.Map的介绍

  并发容器
一:容器的概览
二:集合历史
三:ConcurrentHashMap

   说明一下LinkedHashMap:

  大多数情况下,只要不涉及线程安全问题,Map基本都可以使用HashMap,不过HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序。HashMap的这一缺点往往会带来困扰,因为有些场景,我们期待一个有序的Map。

这个时候,LinkedHashMap就闪亮登场了,它虽然增加了时间和空间上的开销,但是通过维护一个运行于所有条目的双向链表,LinkedHashMap保证了元素迭代的顺序该迭代顺序可以是插入顺序或者是访问顺序。

  

2.为什么HashMap是线程不安全的

  同时put碰撞会导致数据的丢失

  同时put扩容会导致数据的丢失

  死循环造成的cpu100%

3.为什么出现100%

  主要存在于jdk7

  需要使用多线程进行调试

package com.jun.juc.collections;

import java.util.HashMap;

/**
 * 演示cpu100%
 */
public class HashMapLoop {
    private static HashMap<Integer, String> map = new HashMap(2, 1.5f);

    public static void main(String[] args) {
        map.put(1, "A");
        map.put(2, "B");
        map.put(3, "C");
        new Thread(new Runnable() {
            @Override
            public void run() {
                map.put(4, "D");
                System.out.println(map);
            }
        }, "thread1").start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                map.put(5, "E");
                System.out.println(map);
            }
        }, "thread1").start();
    }
}

  

  需要的断点:

  并发容器
一:容器的概览
二:集合历史
三:ConcurrentHashMap

   然后,将两个线程都放到if()那行,然后都放行

  原因:

  因为在同时扩容时候,出现了链表的死循环,环形链表

4.