先看下线程池具体使用小栗子:
public class Test {
public static void main(String[] args) {
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(5));
for(int i=0;i<15;i++){
MyTask myTask = new MyTask(i);
executor.execute(myTask);
System.out.println("线程池中线程数目:"+executor.getPoolSize()+",队列中等待执行的任务数目:"+
executor.getQueue().size()+",已执行玩别的任务数目:"+executor.getCompletedTaskCount());
}
executor.shutdown();
}
}
class MyTask implements Runnable {
private int taskNum;
public MyTask(int num) {
this.taskNum = num;
}
@Override
public void run() {
System.out.println("正在执行task "+taskNum);
try {
Thread.currentThread().sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("task "+taskNum+"执行完毕");
}
}
项目实践小栗子:
public BillMessagePage<SysOrCustomerTotalBalanceVo> selectCustomerAssetsGroupByUser(SysAssetsParams sysAssetsParams) {
long startTime = System.currentTimeMillis();
List<SysOrCustomerTotalBalanceVo> sysOrCustomerTotalBalanceVoList = new CopyOnWriteArrayList<>();
List<Long> userIds = getSysUser();
List<String> subSystem = getSubSystem();
Set<Long> userAllIds = new HashSet<>();
List<Long> allCustomerIds = new CopyOnWriteArrayList<>();
for (String string : subSystem) {
String[] strings = string.split("-");
Integer accountType = Integer.valueOf(strings[0].toUpperCase());
String accountParam = strings[1].toUpperCase();
List<Long> customerIds = billCoinUserPropertyMapper.selectUserIds(accountType, accountParam);
userAllIds.addAll(customerIds);
}
// 过滤掉系统用户信息
userAllIds.removeAll(userIds);
if (Objects.isNull(sysAssetsParams.getUserId())) {
// 默认全部查询
allCustomerIds.addAll(userAllIds);
} else {
// 按搜索条件查询
// userId 不为空
userAllIds.removeAll(userAllIds);
userAllIds.add(sysAssetsParams.getUserId());
allCustomerIds.addAll(userAllIds);
}
logger.info("userAllIds size={}", userAllIds.size());
// 初始化线程池
ExecutorService pool = Executors.newFixedThreadPool(subSystem.size());
// 初始化计数器
CountDownLatch latch = new CountDownLatch(subSystem.size());
Integer coinId = sysAssetsParams.getCoinId();
AssetsBillConfig assetsBillConfig = assetsBillConfigMapper.selectMinCheckOkTime();
Date checkOkTime = assetsBillConfig.getCheckOkTime();
for (String string : subSystem) {
String[] strings = string.split("-");
Integer accountType = Integer.valueOf(strings[0].toUpperCase());
String accountParam = strings[1].toUpperCase();
pool.submit(new Runnable() {
@Override
public void run() {
try {
List<BillCoinUserProperty> billCoinUserPropertyList = new CopyOnWriteArrayList<>();
List<BillCoinUserProperty> billCoinUserProperties = new CopyOnWriteArrayList<>();
List<SysOrCustomerTotalBalanceVo> list = new CopyOnWriteArrayList<>();
if (AccountTypeEnum.SWAP_MAIN.getIntegerCode().equals(accountType)) {
// bill_coin_property_
for (Long userId : allCustomerIds) {
List<BillCoinUserProperty> contractList = billCoinUserPropertyMapper.selectSingleUser(userId, coinId, accountType, accountParam, checkOkTime);
billCoinUserProperties.addAll(contractList);
}
if (CollectionUtils.isNotEmpty(billCoinUserProperties)) {
Map<Integer, List<BillCoinUserProperty>> map = billCoinUserProperties.stream().collect(Collectors.groupingBy(BillCoinUserProperty::getCoinId));
for (Map.Entry<Integer, List<BillCoinUserProperty>> entry : map.entrySet()) {
SysOrCustomerTotalBalanceVo sysOrCustomerTotalBalanceVo = new SysOrCustomerTotalBalanceVo();
List<BillCoinUserProperty> billCoinUserPropertyLists = entry.getValue();
BigDecimal contract = billCoinUserPropertyLists.stream().map(BillCoinUserProperty::getProp1).reduce(BigDecimal.ZERO, BigDecimal::add);
sysOrCustomerTotalBalanceVo.setCoinId(billCoinUserPropertyLists.get(0).getCoinId());
sysOrCustomerTotalBalanceVo.setBalance(contract);
ContractConfigVo contractConfigVo = ContractConfigUtils.getProductConfig(accountParam.toLowerCase());
if (!Objects.isNull(contractConfigVo)) {
String productName = contractConfigVo.getProductName();
sysOrCustomerTotalBalanceVo.setAccountType(productName);
}
list.add(sysOrCustomerTotalBalanceVo);
}
}
} else {
// bill_coin_property_
for (Long userId : allCustomerIds) {
// 从bill_user_ 中查询check_ok_time
BillUser billUser = billUserMapper.selectBySingleUserId(userId, accountType, accountParam);
if (Objects.isNull(billUser)) {
} else {
List<BillCoinUserProperty> spotOtcList = billCoinUserPropertyMapper.selectSingleUser(userId, coinId, accountType, accountParam, billUser.getCheckOkTime());
billCoinUserPropertyList.addAll(spotOtcList);
}
}
if (CollectionUtils.isNotEmpty(billCoinUserPropertyList)) {
Map<Integer, List<BillCoinUserProperty>> map = billCoinUserPropertyList.stream().collect(Collectors.groupingBy(BillCoinUserProperty::getCoinId));
for (Map.Entry<Integer, List<BillCoinUserProperty>> entry : map.entrySet()) {
SysOrCustomerTotalBalanceVo sysOrCustomerTotalBalanceVo = new SysOrCustomerTotalBalanceVo();
List<BillCoinUserProperty> billCoinProperties = entry.getValue();
sysOrCustomerTotalBalanceVo.setCoinId(billCoinProperties.get(0).getCoinId());
sysOrCustomerTotalBalanceVo.setBalance(selectTotalAssets(billCoinProperties));
if (AccountTypeEnum.SPOT.getIntegerCode().equals(accountType)) {
sysOrCustomerTotalBalanceVo.setAccountType(AccountTypeEnum.SPOT.getDesc());
} else if (AccountTypeEnum.OTC.getIntegerCode().equals(accountType)) {
sysOrCustomerTotalBalanceVo.setAccountType(AccountTypeEnum.OTC.getDesc());
}
list.add(sysOrCustomerTotalBalanceVo);
}
}
}
// 按照不同业务系统分组
Map<Integer, List<SysOrCustomerTotalBalanceVo>> map = list.stream().collect(Collectors.groupingBy(SysOrCustomerTotalBalanceVo::getCoinId));
for (Map.Entry<Integer, List<SysOrCustomerTotalBalanceVo>> entry : map.entrySet()) {
List<SysOrCustomerTotalBalanceVo> sysOrCustomerTotalBalanceVos = entry.getValue();
SysOrCustomerTotalBalanceVo sysOrCustomerTotalBalanceVo = new SysOrCustomerTotalBalanceVo();
BigDecimal coinBalance = sysOrCustomerTotalBalanceVos.stream().map(SysOrCustomerTotalBalanceVo::getBalance).reduce(BigDecimal.ZERO, BigDecimal::add);
sysOrCustomerTotalBalanceVo.setBalance(coinBalance);
sysOrCustomerTotalBalanceVo.setCoinId(sysOrCustomerTotalBalanceVos.get(0).getCoinId());
sysOrCustomerTotalBalanceVo.setShowBalance(coinBalance.setScale(8, BigDecimal.ROUND_DOWN).toPlainString());
sysOrCustomerTotalBalanceVo.setAccountType(getAccountTypeName(accountType,accountParam));
sysOrCustomerTotalBalanceVo.setCoinName(selectCoinName(sysOrCustomerTotalBalanceVo.getCoinId()));
sysOrCustomerTotalBalanceVoList.add(sysOrCustomerTotalBalanceVo);
}
} catch (Exception e) {
logger.error("exception", e);
} finally {
// 线程结束-1
latch.countDown();
}
}
});
// List<SysOrCustomerTotalBalanceVo> list = selectSingleSystem(sysAssetsParams, allCustomerIds);
// sysOrCustomerTotalBalanceVoList.addAll(list);
}
try {
// 等待所有线程结束
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
pool.shutdown();
// List<SysOrCustomerTotalBalanceVo> coinList = selectBalanceGroupByCoinId(sysOrCustomerTotalBalanceVoList);
// 分页
BillMessagePage<SysOrCustomerTotalBalanceVo> billMessagePage = selectPaging(sysAssetsParams.getPageNo(), sysAssetsParams.getPageSize(), sysOrCustomerTotalBalanceVoList);
long endTime = System.currentTimeMillis();
System.out.println("程序运行时间:" + (endTime - startTime) + "ms");
logger.info("startTime = {},endTime = {},allAssets time = {}",startTime,endTime,endTime - startTime);
return billMessagePage;
}
使用多线程程序运行时间缩短近三倍,注意arrayList是线程不安全的,要使用线程安全的copyOnWriteList,多个线程之间不可以共用同一个对象,会造成线程不安全