上个帖子(https://blog.csdn.net/lingxinggo/article/details/80008927)说了解析Excel任务,后面对其处理步骤中包含手机号码校验,这个要请求别的系统进行dubbo校验,考虑到性能,将结果分割进行多线程请求,然后结果拼装起来即可。
/**
* Bestpay.com.cn Inc.
* Copyright (c) 2011-2016 All Rights Reserved.
*/
package com.bestpay.messagecenter.product.core.core.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import com.bestpay.messagecenter.product.common.constant.RedisProductKeys;
import com.bestpay.messagecenter.product.core.redis.ConfigRedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.bestpay.basic.service.response.QueryMobileHResponse;
import com.bestpay.messagecenter.oss.common.util.dfa.CollectionUtil;
import com.bestpay.messagecenter.product.common.enums.CarrierTypeEnum;
import com.bestpay.messagecenter.product.common.util.ListUtil;
import com.bestpay.messagecenter.product.core.core.MultiThreadTaskService;
import com.bestpay.messagecenter.product.manager.MessageHcodeManager;
import com.bestpay.messagecenter.product.manager.model.FileItem;
import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
/**
* @author linxing
* @version Id: MultiThreadTaskServiceImpl.java, v 0.1 2017/12/18 10:51 linxing Exp $$
*/
@Service
@Slf4j
public class MultiThreadTaskServiceImpl implements MultiThreadTaskService {
/**
* H码服务
*/
@Autowired
private MessageHcodeManager messageHcodeManager;
@Autowired
private ConfigRedisService configRedisService;
private ExecutorService executor;
private LinkedBlockingQueue<Runnable> linkedBlockingQueue = new LinkedBlockingQueue<>();
private static final Pattern pattern = Pattern.compile("\\d{11}");
@PostConstruct
public void init() {
int core = configRedisService.getConfigInt(RedisProductKeys.getCfgSmsTaskCoreThreadNum());
int max = configRedisService.getConfigInt(RedisProductKeys.getCfgSmsTaskMaxThreadNum());
int aliveTime = configRedisService.getConfigInt(RedisProductKeys.getCfgSmsTaskThreadKeepAliveTime());
executor = new ThreadPoolExecutor(core, max, aliveTime, TimeUnit.SECONDS, linkedBlockingQueue);
}
@PreDestroy
public void destroy() {
executor.shutdown();
}
@Override
public List<FileItem> getTaskFileItems(List<FileItem> fileItems) {
//计算线程数
int threadNum = configRedisService.getConfigInt(RedisProductKeys.getMultiTaskThreadNum());
threadNum = fileItems.size() < 1000 ? 1 : threadNum;
//将任务文件平均分成线程数份
List<List<FileItem>> splitList = ListUtil.averageAssign(fileItems, threadNum);
List<FutureTask<List<FileItem>>> futureTasks = new ArrayList<>();
for (int i = 0; i < threadNum; i++) {
FutureTask<List<FileItem>> ft = new FutureTask<>(new SubTask(splitList.get(i)));
futureTasks.add(ft);
executor.submit(ft);
}
splitList.clear();
List<FileItem> result = new ArrayList<>();
for (FutureTask<List<FileItem>> each : futureTasks) {
try {
//阻塞获取各线程返回的结果
List<FileItem> splitResult = each.get();
result.addAll(splitResult);
} catch (InterruptedException e) {
log.error("MultiThreadTaskServiceImpl getTaskFileItems error:{}",
Throwables.getStackTraceAsString(e));
cancelTask(futureTasks);
Thread.currentThread().interrupt();
return null;
} catch (ExecutionException e) {
log.error("MultiThreadTaskServiceImpl getTaskFileItems error:{}",
Throwables.getStackTraceAsString(e));
cancelTask(futureTasks);
return null;
}
}
if (CollectionUtil.isNotEmpty(fileItems)) {
fileItems.clear();
}
return result;
}
/**
* 尝试终止任务
* @param futureTasks
*/
private void cancelTask(List<FutureTask<List<FileItem>>> futureTasks) {
for (FutureTask<List<FileItem>> each : futureTasks) {
if (each.isDone()) {
continue;
}
each.cancel(true);
}
}
/**
* 子任务-处理分给自己发文件数据
*/
private class SubTask implements Callable<List<FileItem>> {
private List<FileItem> list;
public SubTask(List<FileItem> list) {
this.list = list;
}
@Override
public List<FileItem> call() throws Exception {
for (FileItem each : list) {
String phoneNumber = each.getPhoneNumber();
Matcher matcher = pattern.matcher(phoneNumber);
if (null == phoneNumber || !matcher.matches()) {
each.setErrorInfo("手机号码格式有误");
continue;
}
QueryMobileHResponse res;
try {
//报错-继续请求剩下的手机号
res = messageHcodeManager.queryInfoByMobileNo(phoneNumber);
} catch (Exception e) {
log.error("请求CIF获取运营商错误:{}", Throwables.getStackTraceAsString(e));
each.setErrorInfo("调用CIF失败");
continue;
}
if (res == null) {
each.setErrorInfo("手机号码格式有误");
continue;
}
CarrierTypeEnum carrierType = CarrierTypeEnum.getCarrierType(res.getCarrierName());
if (carrierType == null) {
each.setErrorInfo("手机号码格式有误");
continue;
}
each.setCarrierTypeEnum(carrierType);
}
return list;
}
}
}