Java多线程与并发库高级应用-同步集合
Posted wq3435
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程与并发库高级应用-同步集合相关的知识,希望对你有一定的参考价值。
ArrayBlockingQueue
LinkedBlockingQueue
数组是连续的一片内存
链表是不连续的一片内存
传统方式下用Collections工具类提供的synchronizedCollection方法来获得同步集合。
java5中提供了如下一些同步集合类:
> 通过看java.util.concurrent包下的介绍可以知道有哪些并发集合
> ConcurrentHashMap
> 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); } } }
以上是关于Java多线程与并发库高级应用-同步集合的主要内容,如果未能解决你的问题,请参考以下文章
(黑马Java多线程与并发库高级应用)04 传统线程同步通信技术