请求合并的思想:不是每次请求都建立连接,而是把多个请求进行合并,一起访问数据库,节约空间。
所以必然时间会延长,所以请求合并是:时间换空间。
其实其中的想法,都可以想到,唯一想不到的就是CompletableFuture的使用。
原本的Order类
public class Order {
private String code;
private String name;
private String remark;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Override
public String toString() {
return "Order{" +
"code='" + code + '\'' +
", name='" + name + '\'' +
", remark='" + remark + '\'' +
'}';
}
}
OrderService类
public class OrderService {
static Map<String, Order> orderMap = new HashMap<String, Order>();
static {
for (int i = 10; i < 10000; i++) {
Order order = new Order();
order.setCode("O" + i);
order.setName("Name" + i);
order.setRemark(UUID.randomUUID().toString());
orderMap.put(order.getCode(), order);
}
System.out.println("数据初始完");
}
//批量请求数据库
public List<Order> getByCodes(Set<String> codes) {
try {
//假装连接数据库
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
List<Order> list = new ArrayList<>();
for (String code : codes) {
Order order = orderMap.get(code);
if (order != null) {
list.add(order);
}
}
return list;
}
public Order getByCode(String code) {
try {
//假装连接数据库
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
return orderMap.get(code);
}
}
加入请求合并接口
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;
public class MergeService {
volatile LinkedBlockingQueue<Merge> queue = new LinkedBlockingQueue<>();
Timer timer = new Timer(true);
OrderService orderService = new OrderService();
public MergeService() {
timer.schedule(new MyTask(), new Date(), 10);
}
public Order getByCode(String code) throws ExecutionException, InterruptedException {
Merge merge = new Merge();
CompletableFuture<Order> future = new CompletableFuture<Order>();
merge.setCode(code);
merge.setFuture(future);
queue.add(merge);
return future.get();
}
//简略的定时任务
class MyTask extends TimerTask {
@Override
public void run() {
if (queue.isEmpty()) {
return;
}
Set<String> codes = new HashSet<>(queue.size());
List<Merge> merges = new ArrayList<>(queue.size());
while (!queue.isEmpty()) {
Merge merge = queue.poll();
codes.add(merge.getCode());
merges.add(merge);
}
List<Order> orders = orderService.getByCodes(codes);
Map<String, Order> orderMap = orders.stream().collect(Collectors.toMap(Order::getCode, o -> o));
for (Merge merge : merges) {
Order order = orderMap.get(merge.getCode());
merge.getFuture().complete(order);
}
}
}
}
使用到的Merge对象
public class Merge {
private String code;
private CompletableFuture<Order> future;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public CompletableFuture<Order> getFuture() {
return future;
}
public void setFuture(CompletableFuture<Order> future) {
this.future = future;
}
}
Test类
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
System.out.println("开始" + System.currentTimeMillis());
MergeService mergeService = new MergeService();
OrderService orderService = new OrderService();
int num = 500;
CountDownLatch countDownLatch = new CountDownLatch(num);
for (int i = 0; i < num; i++) {
String code = "O" + i;
new Thread(() -> {
countDownLatch.countDown();
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("组队完成" + System.currentTimeMillis());
try {
System.out.println(Thread.currentThread().toString() + mergeService.getByCode(code) + System.currentTimeMillis());
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println(Thread.currentThread().toString() + orderService.getByCode(code) + System.currentTimeMillis());
}).start();
}
}
}