zoukankan      html  css  js  c++  java
  • Java多线程与并发库高级应用-同步集合

    ArrayBlockingQueue

    LinkedBlockingQueue

    数组是连续的一片内存

    链表是不连续的一片内存

     传统方式下用Collections工具类提供的synchronizedCollection方法来获得同步集合。

    java5中提供了如下一些同步集合类:

      > 通过看java.util.concurrent包下的介绍可以知道有哪些并发集合

      > ConcurrentHashMap 可以进行并发操作的HashMap,并发的HashMap还有 Collections.synchronizedMap(m) ,有了ConcurrentHashMap后,Collections.synchronizedMap(m)不怎么使用了。

      >ConcurrentSkipListMap 实现了SortedMap<K,V>  ,类似于TreeMap

      >ConcurrentSkipListSet 实现了SortedSet, 类似于TreeSet

      > CopyOnWriteArrayList

      > CopyOnWriteArraySet

    传统方式下的Collection在迭代时,不允许对集合进行修改。

    使用Iterator对集合进行迭代时不能修改集合

    public class CollectionModifyExceptionTest {
    
        public static void main(String[] args) {
            List<String> strs = new ArrayList<>();
            strs.add("aaa");
            strs.add("bbb");
            strs.add("ccc");
            Iterator iterator = strs.iterator();
            while(iterator.hasNext()){
                System.out.println(".....");
                String value = (String)iterator.next();
                if("aaa".equals(value)){
                    strs.remove(value);
                }else{
                    System.out.println(value);
                }
            }
        }
    
    }

    以上代码在遍历集合时,对集合进行修改,会抛出异常

    Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at com.java.thread.CollectionModifyExceptionTest.main(CollectionModifyExceptionTest.java:17)

    异常抛在这一句 

    String value = (String)iterator.next();
    /**
         * An optimized version of AbstractList.Itr
         */
        private class Itr implements Iterator<E> {
            int cursor;       // index of next element to return
            int lastRet = -1; // index of last element returned; -1 if no such
            int expectedModCount = modCount;
    
            public boolean hasNext() { //
                return cursor != size;
            }
    
            @SuppressWarnings("unchecked")
            public E next() {
                checkForComodification();
                int i = cursor;
                if (i >= size)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }
    
            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                checkForComodification();
    
                try {
                    ArrayList.this.remove(lastRet);
                    cursor = lastRet;
                    lastRet = -1;
                    expectedModCount = modCount;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
    
            final void checkForComodification() {
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();//此处抛异常
            }
        }

    然而在将"aaa" 改成"bbb"时,却没有抛出异常

    因为在遍历到 bbb 时,cursor为1(0,1,2),将 bbb 移除后size为2 进行下次遍历是cursor为 2

    所以hasNext()返回的为false 就不会进入循环。

    要解决这个问题,可以使用 CopyOnWriteArrayList  在写的时候有一份拷贝,

    public static void main(String[] args) {
            List<String> strs = new CopyOnWriteArrayList();
            strs.add("aaa");
            strs.add("bbb");
            strs.add("ccc");
            Iterator iterator = strs.iterator();
            while(iterator.hasNext()){
                System.out.println(".....");
                String value = (String)iterator.next();
                if("aaa".equals(value)){
                    strs.remove(value);
                }else{
                    System.out.println(value);
                }
            }
        }
  • 相关阅读:
    【原创】tyvj1038 忠诚 & 计蒜客 管家的忠诚 & 线段树(单点更新,区间查询)
    [转载]线段树模板
    并查集相当6的一篇文章~~~
    觉得一篇讲SPFA还不错的文章
    【原创】POJ 3259 Wormholes(Bellman-Ford) && 简介Bellman-Ford算法
    【原创】谈谈数据结构课后作业......尴尬不已...《图》 后面的迷宫问题
    MyBatis源码分析(七):动态代理(Mybatis核心机制)
    1026: [SCOI2009]windy数
    Spring Boot 官方文档学习(一)入门及使用
    Spring Hibernate JPA 联表查询 复杂查询
  • 原文地址:https://www.cnblogs.com/wq3435/p/6049399.html
Copyright © 2011-2022 走看看