代码展示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| 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<>(), 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集合在多线程中会出现线程抢占,从而导致了集合越界
内存角度分析异常原因
1 2 3
| 在Java虚拟机中,内存分为线程内存和主内存;对于每一个线程而言,线程内存会从主内存中读取数据到本地内存,在完成操作后再回写到主内存中 1.线程安全对象: 读取、回写是受控制的 2.线程不安全对象: 会有多个线程同时读取数据到本地,然后出现线程抢占(一个线程还未完成操作,另外一个线程的操作就继续了,另外一个线程的操作就将它的操作冲掉了)
|
线程安全与线程不安全的对象
1 2
| 线程安全对象: Vector, HashTable, StringBuffer 线程不安全对象: ArrayList, LinkedList, HashMap, StringBuilder
|
将线程不安全的对象包装成线程安全的对象的方法
1 2 3
| 1.List类: Collections.synchronizedList(list) 2.Set类: Collections.synchronizedSet(set) 3.Map类: Collections.synchronizedMap(map)
|