这是我参与 8 月更文挑战的第 8 天,活动详情查看: 8月更文挑战
1.集合类线程不安全的场景
在多线程中,ArrayList是线程不安全的。 具体看下面的代码:
package JUC;
import javax.imageio.stream.ImageInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @Author MingJian_Zhu
* @Date 2021/8/11 10:44
*/
public class ContainerNotSateDemo {
public static void main(String[] args) {
ArrayList arrayList = new ArrayList();
// List<String> list = Collections.synchronizedList(new ArrayList<>());
// List<String> arrayList = new CopyOnWriteArrayList<>();
for(int i = 1;i<=30;i++){
new Thread(()->{
arrayList.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(arrayList);
},String.valueOf(i)).start();
}
}
}
上面代码中运行结果出现了ConcurrentModificationException的异常报错,这是由于ArrayList是线程不安全引起的异常。 解决上面的方法:
2.使用线程安全的集合Vector
package JUC;
import javax.imageio.stream.ImageInputStream;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @Author MingJian_Zhu
* @Date 2021/8/11 10:44
*/
public class ContainerNotSateDemo {
public static void main(String[] args) {
List arrayList = new Vector();
for(int i = 1;i<=30;i++){
new Thread(()->{
arrayList.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(arrayList);
},String.valueOf(i)).start();
}
}
}
3.使用Collection类构造线程安全的list
package JUC;
import javax.imageio.stream.ImageInputStream;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @Author MingJian_Zhu
* @Date 2021/8/11 10:44
*/
public class ContainerNotSateDemo {
public static void main(String[] args) {
List<String> arrayList = Collections.synchronizedList(new ArrayList<>());
for(int i = 1;i<=30;i++){
new Thread(()->{
arrayList.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(arrayList);
},String.valueOf(i)).start();
}
}
}
4.使用JUC里面的类:CopyOnWriteArrayList
package JUC;
import javax.imageio.stream.ImageInputStream;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @Author MingJian_Zhu
* @Date 2021/8/11 10:44
*/
public class ContainerNotSateDemo {
public static void main(String[] args) {
List<String> arrayList = new CopyOnWriteArrayList<>();
for(int i = 1;i<=30;i++){
new Thread(()->{
arrayList.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(arrayList);
},String.valueOf(i)).start();
}
}
}
5.总结
在多线程环境下,如何使用安全的集合List类是个重要的问题。在上述的解决方案中,个人推荐使用第二,三种的方法。针对第一种方法,因为Vector中存在着Syncronized的锁,所有在多线程程的使用环境下,会有极大的性能瓶颈问题;而第二和第三种采取的是不加锁的方法实现的。第三种称之为写时复制,该类每次添加元素的时候,都会拷贝上一次的内容出来,然后在其上次添加的元素上面添加元素,并且将原来指向旧的存储元素的空间的引用作废,将拷贝出来的存储空间指向原来的引用。