基于XML的数据库开发-8

    这几天正在看<<Java并发编程实战>>.对于多线程操作有了新的认识.下面介绍一下关于串行转并行的处理.

    为了保证客户端修改数据不会影响到服务端的原始数据,LocalXData在返回搜查结果的时候,会做一次深拷贝.调用的函数如下:

public static Object copyObj(Object obj) {
        Object retdata = null;

        try {
            Class clazz = Class.forName(obj.getClass().getName());
            Constructor[] constructorList = clazz.getDeclaredConstructors();
            Constructor constructor = constructorList[0];
            constructor.setAccessible(true);
            Object membet = constructor.newInstance();
            
            Field[] fieldlist = obj.getClass().getDeclaredFields();
            
            for(Field field:fieldlist) {
                switch (PraseParamUtil.PraseObjectType(field.getType().getName())) {
                    case PraseParamUtil.PRASE_TYPE_INT:
                        Field intField = membet.getClass().getField(field.getName());
                        intField.setInt(membet, field.getInt(obj));
                        break;

                    case PraseParamUtil.PRASE_TYPE_BOOLEAN:
                        Field booleanField = membet.getClass().getField(field.getName());
                        booleanField.setBoolean(membet, field.getBoolean(obj));
                        break;

                    case PraseParamUtil.PRASE_TYPE_FLOAT:
                        Field floatField = membet.getClass().getField(field.getName());
                        floatField.setFloat(membet, field.getFloat(obj));
                        break;

                    case PraseParamUtil.PRASE_TYPE_LONG:
                        Field longField = membet.getClass().getField(field.getName());
                        longField.setLong(membet, field.getLong(obj));
                        break;

                    case PraseParamUtil.PRASE_TYPE_STRING:
                        Field stringField = membet.getClass().getField(field.getName());
                        stringField.set(membet, field.get(obj));
                        break;
                }
            }
            
            return membet;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return retdata;
    }
可以看出,如果数据较多的情况下,调用这个函数复制这个数据就会相当耗时.相关代码如下;

if(dataList != null) {
    	    dataList.enterLooper();
    	    for(DataCell dataCell :dataList) {
    	    	if(dataCell.getState() != DataCell.DATA_DELETE) {
                    list.add(SqlUtil.copyObj(dataCell.obj));
    	    	}
            }
    	    dataList.leaveLooper();
    	}

如果使用多线程处理的话,就可以并行处理copy的操作,而不是如上代码,逐个copy了。具体代码如下:

final Queue<Object>queue = new ConcurrentLinkedQueue<Object>(); 
    	//wangsl use parallel
    	ExecutorService exec = Executors.newFixedThreadPool(10);
    	
    	
    	if(dataList != null) {
    	    dataList.enterLooper();
    	    for(DataCell dataCell :dataList) {
    	    	final DataCell cell = dataCell;
    	    	if(dataCell.getState() != DataCell.DATA_DELETE) {
                    //list.add(SqlUtil.copyObj(dataCell.obj));
    	    		exec.execute(new Runnable() {
						@Override
						public void run() {
							queue.add(SqlUtil.copyObj(cell.obj));
						}
    	    			
    	    		});
    	    	}
            }
    	    dataList.leaveLooper();
    	}
    	//wangsl use parallel
    	
    	exec.shutdown();
    	try {
			exec.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

其中需要注意一点的是:由于Arraylist不是线程安全的,所以如果在多线程同时操作的时候,可能会造成数据丢失(实测的确发生了,50000个数据大约丢失了300个)

所以这里使用了ConcurrentLinkedQueue。


实测50000条数据如果使用循环copy的情况下耗时0.4S

实测50000条数据如果使用多线程copy的情况下耗时0.16S



猜你喜欢

转载自blog.csdn.net/wang_sun_1983/article/details/15692089