ConcurrentModificationException报错处理

一、报错问题解决

    
    public String services(){
        List <Future<Map<String,Object>>> list=new ArrayList<Future<Map<String,Object>>>();
        int total=0;
        //1.准备需要传递的参数
        String condition = dealContent();
        List<CompanyEntity> companyList = companyService.list(condition, -1, -1);
        List<Node> nodeList = new ArrayList<Node>();
        int nodeId = getNodeId();
            if(nodeId != 0){
                Node node = nodeService.getById(nodeId);
                nodeList.add(node);
            }else{
                nodeList = nodeService.getAll();
            }
        List<JSONObject> comList = new ArrayList<JSONObject>();
            for(CompanyEntity company : companyList){
                for(Node node : nodeList){
                    JSONObject jsonObj = new JSONObject();
                    jsonObj.put("companyName", company.getCompanyName());
                    jsonObj.put("companyId", company.getCompanyId());
                    jsonObj.put("companyType", company.getType());
                    jsonObj.put("nodeName",node.getNode_name());
                    jsonObj.put("nodeId",node.getNode_id());
                    jsonObj.put("nodeIp", node.getNode_ip());
                    comList.add(jsonObj);
                }
            }
        //2.数据分页处理
        int pagesize=Integer.parseInt(super.getPagesize());
        int nopage=Integer.parseInt(super.getNowpage());
        int ThrearNum=0;
        if(pagesize>ThreadUtil.CORE_POOL_SIZE){
            ThrearNum=ThreadUtil.CORE_POOL_SIZE;
        }else{
            ThrearNum=pagesize;
        }
        try {
            //计算数据总量:
            int sumDataCount=comList.size();
            List<JSONObject> dataList=new ArrayList<JSONObject>();
            
            final CountDownLatch latch = new CountDownLatch(ThrearNum);
            boolean flag=false;
            int dataEnd=0;
            int addData=0;
            int j=1;
            for (int i = 0; i < ThrearNum; i++) {
                List<JSONObject> addList=new ArrayList<JSONObject>();
                List<JSONObject> tempList=new ArrayList<JSONObject>(comList.size());
                tempList=comList;
                List<JSONObject> dealList=new ArrayList<JSONObject>();
                
                if(sumDataCount%ThrearNum!=0){
                    addData=sumDataCount%ThrearNum;
                    flag=true;
                }
                //计算每个线程要处理的数据总量:
                int dataCountPerThread=sumDataCount/ThrearNum;
                //计算当前线程数据处理的起始索引:
                int dataStart=i*dataCountPerThread;
                //计算当前线程数据处理的结束索引:
                dataEnd=(i+1)*dataCountPerThread;
                //截取List,作为当前线程所需要处理的全部数据:
                if(flag){
                    if(j<=addData){
                        //多余的数据,从最后的索引开始平均分配
                        addList.add(tempList.get(tempList.size()-j));
                        j++;
                    }
                    dealList=subData(tempList,dataStart, dataEnd);
                    if(addList.size()!=0){
                        dealList.add(addList.get(0));
                        addList.remove(0);
                    }
                }else{
                    dealList=subData(tempList,dataStart, dataEnd);
                    //如果这里不使用subData,而是使用subList,则会报错:java.util.ConcurrentModificationException
                    //dealList=comList.subList(dataStart, dataEnd);
                }
                
                Callable<Map<String,Object>> c1 = new CallableCountThread(condition,dealList,VpcFlag,slbFlag,blockFlag,vpnFlag,latch);
                Future<Map<String,Object>> f1=pool.submit(c1);
                list.add(f1);
            }
            
            latch.await();
            for(int i=0;i<list.size();i++){
                Future<Map<String,Object>> f1=list.get(i);
                    total+=(Integer)f1.get().get("count");
                    if(null!=f1.get().get("data")){
                        dataList.addAll((List<JSONObject>)f1.get().get("data"));
                    }
                    
            }
            doPage_special(total);
            //3.查询分页开始和结束的索引位
            int  nowpage2 = (Integer) dataMap.get("nowpage"); 
            int  pagesize2 = (Integer) dataMap.get("pagesize");
            
            List<JSONObject> showData=new ArrayList<JSONObject>();
            if(dataList.size()==0){
                
            }else{
                if(nopage==1){
                    if(dataList.size()<=pagesize2){
                        showData=dataList.subList(0,dataList.size()-1);
                        showData.add(dataList.get(dataList.size()-1));
                    }else{
                        showData=dataList.subList(0,pagesize2);
                    }
                }else{
                    if(dataList.size()<=(nopage)*pagesize2){
                        showData=dataList.subList((nopage-1)*pagesize2,dataList.size()-1);
                        showData.add(dataList.get(dataList.size()-1));
                    }else{
                        showData=dataList.subList((nopage-1)*pagesize2,nopage*pagesize2);
                    }
                }
            }
            generateSuccessListResponse(showData);
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return JSON;
    }

在使用Callablejiek接口实现多线程查询的时候,当时自己采用了subList方法去截取list,传递给xian线程处理。

后续,在查询的过程中,报出了ConcurrentModificationException错误,查资料之后发现,这个错误的核心问题,是由于在duoc多线程环境下,多个线程同时访问or修改同一个对象导致的。

 

百思不得其解。后续,将subListdang方法换成了subData,问题解决:

	public   List<JSONObject> subData( List<JSONObject> list,int start,int end){
		 List<JSONObject> dataList=new ArrayList();
			for(int i=start;i<end;i++){
				dataList.add(list.get(i));
			}
		return dataList;
	}

二、报错原因分析:

究其原因,是因为subList被截取之后,返回的还是原来的list的引用。

大家可以看下面这个小例子:

package com.test.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;

public class SubListTest {
	
	public static List subData(List list,int start,int end){
		List dataList=new ArrayList();
			for(int i=start;i<end;i++){
				dataList.add(list.get(i));
			}
		return dataList;
	}

	public static void main(String[] args) {
		
		//示例一:
		System.out.println("示例一:");
		List list=new ArrayList();
		for(int i =1;i<10;i++){
			list.add(i);
		}
		List list2=new ArrayList();
		System.out.println("list="+list);
		list2=list.subList(2, 3);
		System.out.println("list2="+list2);
		list2.remove(0);
		System.out.println("list="+list);
		
		//示例二:
		System.out.println("示例二:");
		List list3=new ArrayList();
		list3.add(0);
		list3.add(1);
		list3.add(2);
		list3.add(3);
		list3.add(4);
		System.out.println("list3="+list3);
		
		List list4=new ArrayList();
		list4=subData(list3, 0, 2);
		System.out.println("list4="+list4);
		list4.remove(0);
		list4.remove(0);
		System.out.println("list4="+list4);
		System.out.println("list3="+list3);

	}

}

 

 

输出结果:

可以看到,示例一中,list2是由list调用subList之后返回的。但是,对于List2进行删除之后,原本的list的数据3也没了。

而,调用示例二中的自定义方法subData之后,list4的删除,并不会对于list3的数据有任何改变。

 

所以,这就解释了,为什么之前在调用subList方法的时候,多线程环境下会报出ConcurrentModificationException的原因:

因为subList截取之后,返回的还是原来那个对象的引用。你多个线程调用的时候,实际上还是操作的是之前的同一个引用,suoy所以肯定会报出ConcurrentModificationException的错误了!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值