您的位置:首页 > 数据库

基于XML的数据库开发-8

2013-11-12 21:44 399 查看
    这几天正在看<<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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: