业务场景:在查询订单的时候如何增加处理效率,处理的过程中代码对订单的数据进行了循环,查询数据库进行替换值。导致返回速率很低。
首先我的想法将最原始的数据集合进行拆分,分批处理。
集合拆分执行:
//设置list切片大小
int thresholdSize = 300;
//查询出来的数据集合
int rowNum = orderList.size();
int number = rowNum % thresholdSize;
List<Order> orderListAdd = new ArrayList<>();
for (int j = 0, startIndex = 0; ; j++) {
int splitIndex = thresholdSize * (j + 1);
if (startIndex == rowNum) {
break;
}
if (number > 0 && startIndex + number == rowNum) {
splitIndex = rowNum;
}
//处理数据的逻辑
processOrder();
startIndex = splitIndex;
}
这样效率并没有很大的提升,在切片的基础上加上线程池多线程并发执行。
优化后:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
//设置list切片大小
int thresholdSize = 300;
int rowNum = orderList.size();
int number = rowNum % thresholdSize;
List<Order> orderListAdd = new ArrayList<>();
try {
int taskSize = 5;
// 创建一个线程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
// 创建多个有返回值的任务
List<Future> list = new ArrayList<Future>();
for (int j = 0, startIndex = 0; ; j++) {
int splitIndex = thresholdSize * (j + 1);
if (startIndex == rowNum) {
break;
}
if (number > 0 && startIndex + number == rowNum) {
splitIndex = rowNum;
}
Callable c = new OrderThread(orderList.subList(startIndex,splitIndex));
// 执行任务并获取Future对象
Future f = pool.submit(c);
list.add(f);
startIndex = splitIndex;
}
pool.shutdown();
// 获取所有并发任务的运行结果
for (Future f : list) {
orderListAdd.addAll((Collection<? extends Order>) f.get());
}
获得数据。值得注意的是,future模式获得数据,可以有两种形式,即无阻塞和阻塞,分别是isDone和get。上文写的get方法,将阻塞直到该线程运行结束,而future.isDone() return true或false 无阻塞。
线程内部:
import java.util.concurrent.Callable;
@Slf4j
public class OrderThread implements Callable<List<Order>> {
private List<Order> orderList;
public OrderThread(List<Order> orderList) {
this.orderList = orderList;
}
@Override
public List<Order> call() throws Exception {
//处理逻辑
return processOrder();
}
}
如果要在线程中执行自己的方法可以参看原有文章:《关于异步线程无法使用@Autowired 自动注入》