集合容器类线程不安全demo,以及解决方案;
List<String> list = new ArrayList<>();
for (int i = 1; i <= 22; i++){
new Thread(new Runnable() {
@Override
public void run() {
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list);
}
},String.valueOf(i)).start();
}
如图多个线程操作同一个arraylist 会报并发修改异常;
以下说解决方案;
1.List list =new Vector();
vector的add是同步方法,可以解决一致性问题,但是并发性会下降,所以一般不用vector;
3.解决方案2,Collections工具类中提供了synchronizedList,synchronizedMap 等方法,可以创建并发环境下的容器;
List<String> list2 = Collections.synchronizedList(new ArrayList<>());
for (int i = 1; i <= 22; i++){
new Thread(new Runnable() {
@Override
public void run() {
list2.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list2);
}
},String.valueOf(i)).start();
}
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5]
[97094e8f, f0ed1777, 09a000a9, b0139b6a]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61]
[97094e8f, f0ed1777, 09a000a9]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f, d2528c4c]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f, d2528c4c, 0ca0cf66]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f, d2528c4c, 0ca0cf66, 21124d45]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f, d2528c4c, 0ca0cf66, 21124d45, 01c9f7c2]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f, d2528c4c, 0ca0cf66, 21124d45, 01c9f7c2, 657aeb20]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f, d2528c4c, 0ca0cf66, 21124d45, 01c9f7c2, 657aeb20, a9835bcf]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f, d2528c4c, 0ca0cf66, 21124d45, 01c9f7c2, 657aeb20, a9835bcf, b5c384b5]
[97094e8f, f0ed1777, 09a000a9, b0139b6a, 1ebcee80, 77c7bbd1, 78c0735a, cb3f9ae1, da97c567, d2f3b789, 1ae70cd5, 7c703f61, dc1244bd, c208cb1f, d2528c4c, 0ca0cf66, 21124d45, 01c9f7c2, 657aeb20, a9835bcf, b5c384b5, b90ee122]
代码执行正确,不会报错;
4.还有另一种JUC包提供的解决方案
java.util.concurrent
类 CopyOnWriteArrayList<E>;
demo
举一反三,其他类型集合并发的问题示例,以及解决的方法
private static void mapNotSafe() {
// HashMap<String, String> map = new HashMap<>(); 有问题
// Map<String, String> objectObjectMap = Collections.synchronizedMap(new HashMap<>()); 解决
//解决
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
for (int i = 0; i < 55; i++) {
new Thread(new Runnable() {
public void run() {
map.put(UUID.randomUUID().toString().substring(0, 8),UUID.randomUUID().toString().substring(0, 8));
System.out.println(map);
}
},String.valueOf(i)).start();
}
}
private static void setNotSafe() {
// HashSet<String> set = new HashSet<>();
Set<String> set = new CopyOnWriteArraySet<String>();
for (int i = 1; i <= 25; i++) {
new Thread(new Runnable() {
@Override
public void run() {
set.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(set);
}
}, String.valueOf(i)).start();
}
}
private static void listNotSafe() {
// List<String> list = Arrays.asList("a", "b", "c");
// list.forEach(System.out::println);
List<String> list = new ArrayList<>();
// List<String> list = Collections.synchronizedList(new ArrayList<>());
for (int i = 1; i <= 22; i++) {
new Thread(new Runnable() {
@Override
public void run() {
list.add(UUID.randomUUID().toString().substring(0, 8));
System.out.println(list);
}
}, String.valueOf(i)).start();
}
}