代码展示
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
public class ThreadSafeVisualPerformanceTest {
public static int multithreadingToAddData(List<String> list, String name) {
ThreadGroup threadGroup = new ThreadGroup(name);
Runnable runnable = () -> {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
list.add("0");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
};
for (int i = 0; i < 100; i++) new Thread(threadGroup, runnable).start();
while (threadGroup.activeCount() > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return list.size();
}
public static void main(String[] args) {
List<String> nonThreadSafeCollection = new ArrayList<>(),
/* 使用Collections.synchronizedList方法将ArrayList转换成线程安全的集合 */
threadSafeCollection = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < 3; i++) {
/* 清除集合 */
nonThreadSafeCollection.clear();
threadSafeCollection.clear();
int size1 = multithreadingToAddData(nonThreadSafeCollection, "线程不安全集合"),
size2 = multithreadingToAddData(threadSafeCollection, "线程安全集合");
System.out.println("线程不安全集合添加元素数量为: " + size1 + ", 线程安全集合添加元素数量为" + size2);
}
}
}
打印展示
此处的异常信息为线程不安全的ArrayList集合在多线程中会出现线程抢占,从而导致了集合越界
内存角度分析异常原因
在Java虚拟机中,内存分为线程内存和主内存;对于每一个线程而言,线程内存会从主内存中读取数据到本地内存,在完成操作后再回写到主内存中
1.线程安全对象: 读取、回写是受控制的
2.线程不安全对象: 会有多个线程同时读取数据到本地,然后出现线程抢占(一个线程还未完成操作,另外一个线程的操作就继续了,另外一个线程的操作就将它的操作冲掉了)
线程安全与线程不安全的对象
线程安全对象: Vector, HashTable, StringBuffer
线程不安全对象: ArrayList, LinkedList, HashMap, StringBuilder
将线程不安全的对象包装成线程安全的对象的方法
1.List类: Collections.synchronizedList(list)
2.Set类: Collections.synchronizedSet(set)
3.Map类: Collections.synchronizedMap(map)