• 第二部分:并发工具类20->并发容器:哪些坑要填


    1.并发容器

    容器4大类List,Map,Set,Queue
    但不是所有的容器都是线程安全的

    2.非线程安全的容器如何变为线程安全的容器

    把非线程安全的容器封装在对象内部,控制好访问路径就可以了

    3.ArrayList 变为线程安全的的列表

    SafeArrayList

    
    SafeArrayList<T>{
      //封装ArrayList
      List<T> c = new ArrayList<>();
      //控制访问路径
      synchronized
      T get(int idx){
        return c.get(idx);
      }
    
      synchronized
      void add(int idx, T t) {
        c.add(idx, t);
      }
    
      synchronized
      boolean addIfNotExist(T t){
        if(!c.contains(t)) {
          c.add(t);
          return true;
        }
        return false;
      }
    }
    

    4.所有非线程安全的类是不是都可以用这种包装方式来线程安全呢,同步容器

    List list = Collections.synchronizedList(Lists.newArrayList());
    Set set = Collections.synchronizedSet(Sets.newHashSet());
    Map map = Collections.synchronizedMap(Maps.newHashMap());
    

    5.组合操作需要注意竞态条件问题

    即使每个操作都保证原子性,也不能吧奥正组合操作的原子性

    6.用迭代器遍历容器

    synchronized(list){
        Iterator i = list.iterator();
    	while(i.hasNext()){
    	    foo(i.next());
    	}
    }
    

    7.java提供的同步容器还有Vector,Stack,Hashtable

    这3个容器不是基于包装类实现的

    8.并发容器注意事项

    jdk1.5之前的同步容器,性能差,都用synchronized来保证互斥,串行度太高
    jdk1.5之后提供了高性能更高的容器,并发容器
    image

    1. List
      CopyOnWriteArrayList,写的时候会将共享变量重新复制一份出来,读操作完全无锁
      原理是什么
      内部维护了一个数组,成员变量array指向内部数组,所有的读操作都是基于array进行,迭代遍历的也是数组

    增加元素,怎么处理?将array复制一份,新复制的数组上执行添加元素操作,执行完之后,array指向新的数组

    坑:读多写少的场景,可以容忍写的短暂不一致.写入的新元素不能立刻被遍历到.

    1. Map
      ConcurrentHashMap和ConcurrentSkipListMap
      ConcurrentHashMap的key是无序的
      ConcurrentSkipListMap的key是有序的

    key不能为null,否则抛出NullPointerException异常

    ConcurrentSkipListMap里面的SkipList本身就是一种数据结构,中文一版称为跳表,时间复杂度O(log n),理论上和并发线程数没有关系

    1. Set
      CopyOnWriteArraySet和ConcurrentSkipListSet

    2. Queue
      阻塞,非阻塞

    阻塞:当队列已满,入队操作阻塞,队列已空,出队操作阻塞;Blocking标识
    单端,双端:单端只能是队尾入队,队首出队,Queue标识;双端队首对尾都可以入队出队,Deque标识;

    4.1 单端阻塞队列
    ArrayBlockQueue,LinkedBlockQueue,SynchronousQueue,LinkedTransferQueue,PriorityBlockingQueue和DelayQueue
    内部队列,数组,甚至不持有队列
    没有队列,生产线程的入队操作必须等待消费线程出队操作。

    4.2 双端阻塞队列
    LinkedBlockingDeque

    4.3 单端非阻塞队列
    ConcurrentLinkedQueue

    4.4 双端非阻塞队列
    ConcurrentLinkedDeque

    原创:做时间的朋友
  • 相关阅读:
    hdu 1028 母函数 一个数有几种相加方式
    第m个全排列
    大数处理
    并查集
    KMP算法及KMP算法的应用(POJ2406)
    算法---分治法
    末学者笔记--NTP服务和DNS服务
    末学者笔记--NFS服务和DHCP服务讲解
    末学者笔记--SSHD服务及SCP用法
    末学者笔记——SAMBA服务、FTP服务讲解
  • 原文地址:https://www.cnblogs.com/PythonOrg/p/14978131.html
Copyright © 2020-2023  润新知