List的线程安全

1,593

@TOC

背景

Q:今天遇到一个场景,我们业务需要使用批量的数据进行操作,但是别人的接口只支持一个一个的查,所以需要用多线程去查结果值再将返回的结果组装成一个list再进行后期的业务逻辑实现。

实验

用哪个list呢?写了一个小demo

1. ArrayList

使用我们平常经常用的ArrayList进行测试

public class SetThread implements Runnable {

    private List<Long> indeLong;

    public SetThread(List<Long> indeLong) {
        this.indeLong = indeLong;
    }

    @Override
    public void run() {
        for (int i = 0; i < 50000; i++) {
            indeLong.add(Long.valueOf(i));
        }
    }
}

public class MyMain {
    public static void main(String[] args) throws InterruptedException {

        // 初始化一个数组 设置大小为200000
        List<Long> sycList = new ArrayList<>(200000);

        SetThread setRunnable1 = new SetThread(sycList);
        Thread thread1 = new Thread(setRunnable1);
        SetThread setRunnable2 = new SetThread(sycList);
        Thread thread2 = new Thread(setRunnable2);
        SetThread setRunnable3 = new SetThread(sycList);
        Thread thread3 = new Thread(setRunnable3);
        SetThread setRunnable5 = new SetThread(sycList);
        Thread thread5 = new Thread(setRunnable5);

        thread1.start();
        thread2.start();
        thread3.start();
        thread5.start();

        thread1.join();      // 主线程等待子线程执行完毕
        thread2.join();
        thread3.join();
        thread5.join();
        System.out.println(sycList.size());
    }

但是返回的结果值不是我们预期的200000个

在这里插入图片描述

2. synchronizedList

再次使用线程安全的synchronizedList测试

public class MyMain {
    public static void main(String[] args) throws InterruptedException {
        // 初始化一个数组
        List<Long> originList = new ArrayList<>();
        List<Long> sycList = Collections.synchronizedList(originList);

        SetThread setRunnable1 = new SetThread(sycList);
        Thread thread1 = new Thread(setRunnable1);
        SetThread setRunnable2 = new SetThread(sycList);
        Thread thread2 = new Thread(setRunnable2);
        SetThread setRunnable3 = new SetThread(sycList);
        Thread thread3 = new Thread(setRunnable3);
        SetThread setRunnable5 = new SetThread(sycList);
        Thread thread5 = new Thread(setRunnable5);

        thread1.start();
        thread2.start();
        thread3.start();
        thread5.start();

        thread1.join();      // 主线程等待子线程执行完毕
        thread2.join();
        thread3.join();
        thread5.join();
        System.out.println(sycList.size());
    }
}

使用线程安全的List之后每次执行都是准确返回200000个 在这里插入图片描述

3. 运行抛出异常

中间还有个小插曲,使用ArrayList进行操作不设置最开始的initialCapacity值的测试

public class MyMain {
    public static void main(String[] args) throws InterruptedException {

        // 初始化一个数组(不设置数组长度)
        List<Long> sycList = new ArrayList<>();

        SetThread setRunnable1 = new SetThread(sycList);
        Thread thread1 = new Thread(setRunnable1);
        SetThread setRunnable2 = new SetThread(sycList);
        Thread thread2 = new Thread(setRunnable2);
        SetThread setRunnable3 = new SetThread(sycList);
        Thread thread3 = new Thread(setRunnable3);
        SetThread setRunnable5 = new SetThread(sycList);
        Thread thread5 = new Thread(setRunnable5);

        thread1.start();
        thread2.start();
        thread3.start();
        thread5.start();

        thread1.join();      // 主线程等待子线程执行完毕
        thread2.join();
        thread3.join();
        thread5.join();
        System.out.println(sycList.size());
    }

抛出了异常:

在这里插入图片描述

ArrayIndexOutOfBoundsException异常原因

todo 后续有时间再补充😂