线程安全遇到的问题——(arraylist的add方法出现下角标越界)

public Map<String, List<Integer>> register(String userName, String passWd, int start, int end) throws InterruptedException {

        List<Future<Map<String, List<Integer>>>> futures = new ArrayList<>();
        Map<String, List<Integer>> listMap = new ConcurrentHashMap<>();
        CountDownLatch downLatch = new CountDownLatch(end-start+1);
        for (int i = start; i <= end; i++) {
            int finalI = i;
            int finalI1 = i;
            Future<Map<String, List<Integer>>> submit = pool.submit(() -> {
                Connection.Response user = Jsoup.connect(LOGIN_FORM_URL)
                        .method(Connection.Method.POST)
                        .referrer(REFERER_URL)
                        .data("u_user", userName + finalI1)
                        .data("u_pass", passWd)
                        .execute();

                String errorMessage = user.body().replace("{F}","");
                //synchronized(this){
                    if (listMap.containsKey(errorMessage)) {
                        listMap.get(errorMessage).add(finalI);
                    } else {
                        ArrayList<Integer> list = new ArrayList<>();
                        list.add(finalI);
                        listMap.put(errorMessage, list);
                    }
                //}

                return listMap;
            });
            futures.add(submit);
            downLatch.countDown();
        }
        downLatch.await();
        for (Future<Map<String, List<Integer>>> future : futures) {
            try {
                future.get();
            }catch (Exception e){
                log.error(Throwables.getStackTraceAsString(e));
            }

        }
        return listMap;
    }

这段代码这个位置还存在2处线程安全问题,具体位置如下:

if (listMap.containsKey(errorMessage)) {
listMap.get(errorMessage).add(finalI);
} else {
ArrayList list = new ArrayList<>();
list.add(finalI);
listMap.put(errorMessage, list);

}
正确结果:[4, 3, 5, 1, 7, 6, 9, 8,2]

  1. if判断,如果list不存在就new一个,若开始多个进程同时进入else逻辑导致后面的new的list覆盖前面new的list,导致list数据比正常偏小
    导致异常结果:[3, 4, 1, 8]

  2. ArrayList本身存在线程安全问题
    list源码如下:

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!! 1
        elementData[size++] = e;  //2
        return true;
    }

先判断扩容,再进行赋值,所有存在多个线程在1,2之间,arraylist默认长度为10,两个线程都判断刚好是10都进入了第二步,则会出现一个线程下角标越界的异常出现。

在这里插入图片描述
最简单的解决方法就是加
synchronized(this){
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值