线程安全与线程不安全的直观表现

180 阅读1分钟

代码展示

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)