- 同步类容器都是线程安全的,但某些情况下可能需要加锁来保护符合操作
- 复合操作:迭代(反复访问元素,遍历完容器中所有的元素);跳转(根据指定的顺序找到当前元素的下一个元素);条件运算
- 这些复合操作在多线程并发地修改容器时,可能会表现出意外的行为,最经典的便是ConcurrentModificationException,原因是当容器迭代的过程中,被并发的修改了内容,这是由于早期迭代器设计的时候并没有考虑并发修改的问
异常代码及解决方法
1 package com.bfxy.thread.cord.collection; 2 3 import java.util.ArrayList; 4 import java.util.Collection; 5 import java.util.Collections; 6 import java.util.Iterator; 7 import java.util.List; 8 import java.util.Vector; 9 import java.util.concurrent.ConcurrentHashMap; 10 11 public class UseSyncCollection { 12 13 // 出现java.util.ConcurrentModificationException 增强for循环是多线程 不允许遍历时修改容器的元素 14 public Collection<String> m1(Vector<String> list) { 15 for (String temp : list) { 16 if ("3".equals(temp)) { 17 list.remove(temp); 18 } 19 } 20 return list; 21 22 } 23 // 出现java.util.ConcurrentModificationException iterator是多线程 不允许遍历时修改容器内元素 24 public Collection<String> m2(Vector<String> list) { 25 Iterator<String> iterator = list.iterator(); 26 while (iterator.hasNext()) { 27 String temp = iterator.next(); 28 if ("3".equals(temp)) { 29 list.remove(temp); 30 } 31 } 32 return list; 33 34 } 35 //successful! 单线程 36 public Collection<String> m3(Vector<String> list) { 37 for (int i = 0; i < list.size(); i++) { 38 if ("3".equals(list.get(i))) { 39 list.remove(i); 40 } 41 } 42 return list; 43 } 44 45 46 public static void main(String[] args) { 47 48 Vector v = new Vector<>(); 49 v.add("1"); 50 v.add("2"); 51 v.add("3"); 52 UseSyncCollection test = new UseSyncCollection(); 53 Collection<String> ret1 = test.m1(v); 54 System.err.println(ret1.toString()); 55 56 // Collection<String> ret2 = test.m2(v); 57 // System.err.println(ret2.toString()); 58 59 // Collection<String> ret3 = test.m3(v); 60 // System.err.println(ret3.toString()); 61 62 63 // List<String> list = new ArrayList<>(); 64 // Collections.synchronizedCollection(list); 65 66 } 67 }