请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

ArrayList测试线程不安全时会抛出异常

在线程不安全类与写法这一节测试ArrayList时遇到问题,代码如下,和老师的一样,没什么区别:
public class ArrayListExample {
//请求总数
public static int clientTotal = 5000;
//同时并发执行的线程数
public static int threadLocal = 200;

public static List<Integer> list = new ArrayList<>();

public static void main(String[] args) throws InterruptedException{
    //定义线程池
    ExecutorService executorService = Executors.newCachedThreadPool();
    //定义信号量,允许并发的数目为200
    final Semaphore semaphore = new Semaphore(threadLocal);
    //定义CountDownLatch
    final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);

    for (int i = 0; i < clientTotal; i++) {
        final int count = i;
        //将所有请求放入到线程池中执行
        executorService.execute(() ->{
            try {
                semaphore.acquire();
                update(count);
                semaphore.release();
            } catch (InterruptedException e) {
                log.error("InterruptedException",e);
            }
            //线程每执行完一次add操作时,就调用countDownLatch
            countDownLatch.countDown();
        });
    }
    //保证countDownLatch的值为0,即所有的线程都执行完毕
    countDownLatch.await();
    //关闭线程池
    executorService.shutdown();
    log.info("list size:{}",list.size());
}

private static void update(int i){
    list.add(i);
}

}

但是这段代码在运行的时候却偶尔会抛出异常:
图片描述
当然,有时候也会运行出正确的结果来,想请教一下老师这里为什么数组下标会越界,ArrayList在扩容时还有什么讲究吗?

正在回答

1回答

Jimin 2019-08-14 22:14:34

你好,本质上就是多个线程都会过来修改,因为没做同步处理,不同线程操作时出现线程不安全,也证实了这个类是线程不安全类。你遇到的问题属于一个比较经典的问题,你看一下这篇文章的演示吧,https://www.cnblogs.com/smellpawn/p/10841480.html

0 回复 有任何疑惑可以回复我~
  • 提问者 qq_超人不会飞_22 #1
    感谢老师的解答,本来今晚想偷懒的,看来条件不允许了^_^
    回复 有任何疑惑可以回复我~ 2019-08-14 22:41:07
  • 提问者 qq_超人不会飞_22 #2
    感觉这里异常的原因和doubleCheck方式实现单例模式可能抛出的异常有异曲同工之处,new一个对象不是原子操作,因此多线程下可能会出错,ArrayList添加元素时,赋值的操作和size++也不是原子操作,因此多线程下也会出错。不知道我这样理解算正确吗
    回复 有任何疑惑可以回复我~ 2019-08-14 23:05:31
  • Jimin 回复 提问者 qq_超人不会飞_22 #3
    嗯,基本上是正确的,多线程下执行i++都会有问题
    回复 有任何疑惑可以回复我~ 2019-08-15 23:35:29
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信