List不安全
解决方法:
1、List list = new Vector<>();
2、List list = Collections.synchronizedList(new ArrayList<>());
3、List list = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList
写入时复制(CopyOnWrite)思想
写入时复制(CopyOnWrite,简称COW)思想是计算机程序设计领域中的一种优化策略。其核心思想是,如果有多个调用者(Callers)同时要求相同的资源(如内存或者是磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的(transparently)。此做法主要的优点是如果调用者没有修改资源,就不会有副本(private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源。
// java.util.ConcurrentModificationException 并发修改异常!
public class ListTest {
public static void main(String[] args) {
// 并发下 ArrayList是不安全的
/*
解决方法 List<String> list = new CopyOnWriteArrayList<>();
写入时复制
*/
List<String> list = new CopyOnWriteArrayList<>();
for (int i = 0; i < 10; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString());
System.out.println(list);
}).start();
}
}
}
Set不安全
解决方法:
- Set set1 = Collections.synchronizedSet(new HashSet<>());
- Set set = new CopyOnWriteArraySet<>();
CopyOnWriteArraySet
// java.util.ConcurrentModificationException 并发修改异常!
public class SetTest {
public static void main(String[] args) {
Set<String> set = new CopyOnWriteArraySet<>();
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(UUID.randomUUID().toString());
}).start();
}
}
}
HashSet底层就是HashMap
public HashSet() {
map = new HashMap<>();
}
// add set 本质就是 map key是无法重复的!
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
private static final Object PRESENT = new Object(); // 不变得值!
HashMap不安全
解决方法:
- Map<String,Object> map = new ConcurrentHashMap<>();
ConcurrentHashMap
package com.it.unsale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author shkstart
* @create 2020-06-18 10:57
*/
public class HashMapTest {
public static void main(String[] args) {
Map<String,Object> map = new ConcurrentHashMap<>();
for (int i = 0; i < 30; i++) {
new Thread(()->{
map.put("xxx",123);
}).start();
}
}
}
Callable类
Callable的特点
1、可以有返回值
2、可以抛出异常
3、方法不同,run()/ call()
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread myThread = new MyThread();
// 适配类
FutureTask futureTask = new FutureTask(myThread);
// 传递适配器 启动线程
new Thread(futureTask).start();
// 获取返回值(可能产生阻塞)
// 阻塞解决方法 将get方法放到最后
String o = (String) futureTask.get();
System.out.println(o);
}
}
// 实现Callable接口
class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("call()");
return "abc";
}
}