在实际的编码过程中,总会遇到单一处理会有性能风险的问题,于是我们求助于批量或者多线程。
一、批量处理
一般情况下批量处理就可以规避大部分性能风险的问题。将fetch(),改为batchFetch(),多数情况都比较简单,尤其是调用其他应用的接口时,将单一接口,换成批量接口即可;而最终主要是修改数据从数据库中的增删改查的方式。
二、多线程
但是有时批量处理不能满足需求,比如需要调用外部的批量接口,但是外部接口不支持,或者可以添加批量接口,但是发现批量取数据库的效率仍然不满足性能需求,那么只能求助于多线程了,其中每个线程都是批量处理,这样更加提升了效率。
/**
* 并行处理控制参数
*/
public class ParallelParameter {
/**
* 是否需要并行处理
*/
private boolean isNeedParallel = false;
/**
* 单个线程是否需要批量处理
*/
private boolean isNeedBatchProcessPerThread = false;
/***
* 单条线程处理的个数,默认为4
*/
private int countPreThread = 4;
public ParallelParameter() {}
public ParallelParameter(boolean isNeedParallel, int countPreThread) {
this.isNeedParallel = isNeedParallel;
this.countPreThread = countPreThread;
}
public ParallelParameter(boolean isNeedParallel,boolean isNeedBatchProcessPerThread, int countPreThread) {
this.isNeedParallel = isNeedParallel;
this.countPreThread = countPreThread;
this.isNeedBatchProcessPerThread = isNeedBatchProcessPerThread;
}
}
/**
* 串行
* @param userList
* @param dtoList
* @param code
* @param typeList
*/
private void serialBatch(List<User> userList, List<T> dtoList, String code, List<Type> typeList) {
List<T> dtoResult = processBatch(userList,code,typeList);
if(null != dtoResult) {
dtoList.addAll(dtoResult);
}
}
/**
* 并行并且每个线程都是批量执行
* @param userList
* @param dtoList
* @param code
* @param typeList
*/
private void parallelBatch(final List<User> userList, final List<T> dtoList, final String code, final List<Type> typeList, final ParallelParameter parallelParameter) {
logger.info("Try to parallel process");
int size = userList.size();
if(0 == size) {
return;
}
int taskCount = (userList.size() + parallelParameter.countPreThread - 1) / parallelParameter.countPreThread;
logger.info(String.format("User count %d", size));
logger.info(String.format("Parallel process task count %d", taskCount));
// 这个等待所有的task完成一起返回
final CountDownLatch latch = new CountDownLatch(taskCount);
for(int i = 0; i < taskCount; i++) {
final int index = i;
threadpool.execute(new Runnable() {
@Override
public void run() {
try {
List<T> dtoResult = null;
int start = index * parallelParameter.countPreThread;
int end = start + parallelParameter.countPreThread;
if(end > userList.size()) {
end = userList.size();
}
List<User> newuserList = new ArrayList<User>();
for(; start < end; start++) {
newuserList.add(userList.get(start));
}
try {
dtoResult = processBatch(newuserList, code, typeList);
if(null != dtoResult) {
int i = 0;
for(int liststart = index * parallelParameter.countPreThread; liststart < end; liststart++){
dtoList.set(liststart, dtoResult.get(i));
i+=1;
}
}
} catch (Throwable t) {
logger.error("Process one User failed, skip", t);
}
} finally {
// 完成一个任务
latch.countDown();
}
}
});
}
// 等待所有的并行task完成
try {
latch.await();
} catch(InterruptedException e) {
logger.error("Wait parallel process failed, interrupted", e);
Thread.currentThread().interrupt();
}
}
/**
* 批量处理
* @param user
* @param code
* @param typeList
*/
protected List<T> processBatch(List<User> userList, String code, List<Type> typeList) {
List<T> dtoList = null;
if (null != code) {
List<User> newList = new ArrayList<User>();
for(User user : UserList){
if (code.equals(user.getMarker())) {
newList.add(user);
}
}
if(!newList.isEmpty()){
dtoList = this.getResouceList(newList, typeList);
}
} else {
dtoList = this.getResouceList(UserList, typeList);
}
return dtoList;
}