在做使用多线程完成数据库查询之前,我们先理清逻辑,使用分页的方式,每个线程完成对应的查询。
我们首先得有个工具类 来帮我们理好每个线程它分页的起始索引,以及它们所要查询的数量。
我的业务是查车辆的轨迹gps信号。
package com.htzn.pm.truck.util;
import java.util.HashMap;
import java.util.Map;
public class SplitUtil {
// 根据查询记录数和线程数量分配每条线程查询记录数
public static Map<String, String> splitMap(int count, int threadCoreNum) {
Map<String, String> splitMap = new HashMap<>(threadCoreNum);
// 每个线程分配的查询记录数
int offsetNum = count / threadCoreNum;
int residue = count % threadCoreNum;
for (int i = 1; i <= threadCoreNum; i++) {
if (i == 1) {
splitMap.put(String.valueOf(i), i - 1 + ":" + offsetNum);
} else if(i < threadCoreNum) {
splitMap.put(String.valueOf(i), (i - 1) * offsetNum + ":" + offsetNum);
} else {
splitMap.put(String.valueOf(i), (i - 1) * offsetNum + ":" + (offsetNum + residue));
}
}
return splitMap;
}
}
然后先把我们所会用到的接口都先写好,
public interface ITaskDetailsService
{
public List<DeviceGpsDto> selectDeviceGps(Long taskId,String deviceId);
}
@Service
public class TaskDetailsServiceImpl implements ITaskDetailsService
{
@Override
public List<DeviceGpsDto> selectDeviceGps(Long taskId, String deviceId) {
ExecutorService executorService = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10));
//获取总记录条数
int count = deviceGpsMapper.getCount(taskId, deviceId);
System.out.println("count"+count);
Map<String, String> splitMap = SplitUtil.splitMap(count, corePoolSize);
List<Callable<List>> tasks = new ArrayList<>();
for (int i = 1; i <= corePoolSize; i++) {
String[] split = splitMap.get(String.valueOf(i)).split(":");
// 查询结果的索引值
int index = Integer.parseInt(split[0]);
// 查询的数量
int num = Integer.parseInt(split[1]);
//获得结果
Callable<List> res = new ThreadQuery(() -> deviceGpsMapper.selectBackGps(taskId, deviceId, index, num));
tasks.add(res);
}
List<DeviceGpsDto> result = new ArrayList<>();
try {
// Future获取结果
List<Future<List>> futures = executorService.invokeAll(tasks);
if (futures != null && futures.size() > 0) {
// 迭代结果
for (Future<List> future : futures) {
result.addAll(future.get());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} finally {
// 关闭线程池
executorService.shutdown();
while (true){
if (executorService.isTerminated()){
System.out.println("任务已完成");
break;
}
}
}
for (int i1 = 0; i1 < result.size(); i1++) {
result.get(i1).setTime((double) (i1*5));
}
return result;
}
}
模板接口
package com.htzn.pm.truck.service;
public interface CommonService <T>{
T template();
}
线程接口类
package com.htzn.pm.truck.thread;
import com.htzn.pm.truck.service.CommonService;
import java.util.List;
import java.util.concurrent.Callable;
public class ThreadQuery implements Callable<List> {
private CommonService baseService;
public ThreadQuery() {}
public ThreadQuery(CommonService baseService) {
this.baseService = baseService;
}
@Override
public List call() throws Exception {
// 查询数据库
return (List) baseService.template();
}
public CommonService getBaseService() {
return baseService;
}
public void setBaseService(CommonService baseService) {
this.baseService = baseService;
}
}