一、CompletableFuture
private static boolean asyncPay() {
CompletableFuture<Boolean> isVaild = CompletableFuture.supplyAsync(() -> CheckService.isVaild());
CompletableFuture<Integer> orderSum = CompletableFuture.supplyAsync(() -> OrderService.create());
CompletableFuture<Integer> money = CompletableFuture.supplyAsync(() -> basePay());
CompletableFuture.allOf(isVaild, orderSum, money)
.thenRun(() -> {
System.out.println("完成异步支付");
}).join();
try {
System.out.println("完成异步支付all" + isVaild.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return true;
}
二、多线程
public Object getUserInfoConcurrent(Long userId) {
long start = System.currentTimeMillis();
// 用户信息
Callable userInfoCall = new Callable() {
@Override
public Object call() throws Exception {
return remoteService.getUserInfo(userId);
}
};
FutureTask<String> userFutureTask = new FutureTask<String>(userInfoCall);
new Thread(userFutureTask).start();
// 钱包余额信息
Callable walletCall = new Callable() {
@Override
public Object call() throws Exception {
return remoteService.getUserWallet(userId);
}
};
FutureTask<String> walletFutureTask = new FutureTask<String>(walletCall);
new Thread(walletFutureTask).start();
Map result = null;
try {
result = new HashMap(2);
result.put("userInfo", userFutureTask.get());
result.put("userWallet", walletFutureTask.get());
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("cost time=" + (System.currentTimeMillis() - start));
return result;
}
三、阻塞队列形式
*** 该方案建议读操作,不要用于写操作
// 请求实例
@GetMapping("/getInfo4")
public Object getUserOrderInfo4(@RequestParam("userId") Long userId) throws Exception {
// return userService.getUserInfo(userId);
long start = System.currentTimeMillis();
Map<String, Object> stringObjectMap = userService.queryOrderBatch(String.valueOf(userId));
System.out.println("getUserInfo4:cost time=" + (System.currentTimeMillis() - start));
return stringObjectMap;
}
// 请求放入队列
public Map<String, Object> queryOrderBatch(String orderCode) {
if (queue.size() > 2000) {
System.out.println("超出限制。。。。。。。。");
return new HashMap<>();
}
String uniqueSerialNo = UUID.randomUUID().toString();
CompletableFuture<Map<String, Object>> future = new CompletableFuture<>();
Request request = new Request();
request.uniqueSerialNo = uniqueSerialNo;
request.orderFuture = future;
request.orderCode = orderCode;
queue.add(request);
try {
return future.get(3,TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
return new HashMap<>();
}
static class Request {
String uniqueSerialNo;
String orderCode;
CompletableFuture<Map<String, Object>> orderFuture;
}
/**
* <p>队列(阻塞队列)</p>
*/
LinkedBlockingDeque<Request> queue = new LinkedBlockingDeque<>();
// 定时任务处理
@PostConstruct
public void initScheduledPool() throws InterruptedException {
System.out.println("initScheduledPool->初始化线程池子");
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(7);
threadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
int size = queue.size();
// System.out.println("批量请求1size=" + size);
if (size < 1) {
return;
}
// 根据接口来封装批量参数
List<Map<String, Object>> params = new ArrayList<>(size);
ArrayList<Request> requests = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
Request request = queue.poll();
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("uniqueSerialNo", request.uniqueSerialNo);
paramMap.put("orderCode", request.orderCode);
params.add(paramMap);
requests.add(request);
}
System.out.println(Thread.currentThread().getName() + "->批量请求size=" + size);
List<Map<String, Object>> responses = null;
try {
responses = remoteService.getOrderInfoByOrderCodeBatch(params);
} catch (Exception e) {
e.printStackTrace();
// 处理异常
for (Request request : requests) {
// request.orderFuture.complete(null);
request.orderFuture.completeExceptionally(e);
}
}
if (CollectionUtils.isEmpty(responses)) {
return;
}
for (Request request : requests) {
for (Map<String, Object> res : responses) {
if (request.uniqueSerialNo.equals(String.valueOf(res.get("uniqueSerialNo")))) {
request.orderFuture.complete(res);
break;
}
}
}
}
}, 100, 10, TimeUnit.MILLISECONDS);
}
四、阻塞队列形式优化版
/**
* <p>Note:
* 1、接收请求
* 2、将请求封装成TransferContext
* 3、将TransferContext添加到阻塞队列transferContextQueue
* 4、利用任务线程池,执行ScheduledTask任务消费阻塞队列的TransferContext,
* 5、ScheduledTask处理调用接口并封装返回结果
* 6、填充completeFuture中的返回结果
* *** 该方案建议读操作,不要用于写操作
* @author xiaocuizi
* @since 1.0.0 2022/3/27 下午10:00
*/
public final class TransferStation {
/**
* <p>阻塞队列最大容量</p>
*/
private final int capacity;
public TransferStation() {
this(2000);
}
public TransferStation(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException();
}
this.capacity = capacity;
this.transferContextQueue = new LinkedBlockingQueue<>(this.capacity);
}
/**
* <p>队列(阻塞队列)</p>
*/
private final BlockingQueue<TransferContext> transferContextQueue;
public BlockingQueue<TransferContext> getTransferContextQueue() {
return transferContextQueue;
}
/**
* -------------------------------------------------------------------------------------------------------------------------------------------
*/
public static class ScheduledTask<T, R> implements Runnable {
private final TransferService<T, R> service;
private final BlockingQueue<TransferContext> transferContextQueue;
public ScheduledTask(BlockingQueue<TransferContext> transferContextQueue, TransferService service) {
this.transferContextQueue = transferContextQueue;
this.service = service;
}
@Override
public void run() {
int size = transferContextQueue.size();
if (size < 1) {
return;
}
// 根据接口来封装批量参数
List<TransferContext> transferContexts = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
// 从队列中获取请求
TransferContext transferContext = transferContextQueue.poll();
if (transferContext == null) {
continue;
}
transferContexts.add(transferContext);
}
if (CollectionUtils.isEmpty(transferContexts)) {
return;
}
// todo 日志修改
// System.out.println(Thread.currentThread().getName() + "->批量请求size=" + size);
List<TransferContext> responseContextList = null;
try {
responseContextList = service.invokeRemote(transferContexts);
} catch (Exception e) {
// todo 日志打印
e.printStackTrace();
transferContexts.forEach(req -> req.comFuture.completeExceptionally(e));
}
if (CollectionUtils.isEmpty(responseContextList)) {
return;
}
// 单条数据
if (transferContexts.size() == 1 && responseContextList.size() == 1) {
if (transferContexts.get(0).uniqueSerialNo.equals(responseContextList.get(0).uniqueSerialNo)) {
transferContexts.get(0).comFuture.complete(responseContextList.get(0).getData());
} else {
transferContexts.get(0).comFuture.complete(null);
}
return;
}
// 多条数据
// uniqueSerialNo ->TransferContext
Map<String, TransferContext> responseContextMap = responseContextList.stream()
.collect(Collectors.toMap(TransferContext::getUniqueSerialNo, Function.identity()));
// 根据uniqueSerialNo进行匹配返回响应结果
for (TransferContext transferContext : transferContexts) {
TransferContext resp = responseContextMap.get(transferContext.uniqueSerialNo);
if (resp != null) {
// 填充返回结果
transferContext.comFuture.complete(resp.data);
}
}
}
}
public static class TransferContext<T, R> {
/**
* <p>请求唯一序列号</p>
*/
private String uniqueSerialNo;
/**
* <p>请求参数
*/
private T param;
/**
* <p>返回结果
*/
private Object data;
/**
* <p>CompletableFuture
*/
private CompletableFuture<R> comFuture;
public TransferContext(String uniqueSerialNo, T param, CompletableFuture<R> comFuture) {
this.uniqueSerialNo = uniqueSerialNo;
this.param = param;
this.comFuture = comFuture;
}
public String getUniqueSerialNo() {
return uniqueSerialNo;
}
public void setUniqueSerialNo(String uniqueSerialNo) {
this.uniqueSerialNo = uniqueSerialNo;
}
public T getParam() {
return param;
}
public void setParam(T param) {
this.param = param;
}
public CompletableFuture<R> getComFuture() {
return comFuture;
}
public void setComFuture(CompletableFuture<R> comFuture) {
this.comFuture = comFuture;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
/**
* <p>
* 主要初始化线程池执行ScheduledTask任务
*
* </p>
*/
public interface TransferService<T, R> {
/**
* <p>初始化线程池子</p>
*/
void initScheduledPool();
/**
* <p>将请求封装,添加至阻塞队列中</p>
*
* @param param 请求参数
* @return {@link R} 返回结果
* @throws Exception
*/
R doRequest(T param) throws Exception;
/**
* <p>将请求封装,添加至阻塞队列中</p>
*
* @param transferStation 对象
* @param param 请求参数
* @return {@link R} 返回结果
* @throws Exception
*/
default R baseRequest(T param, TransferStation transferStation) throws Exception {
BlockingQueue<TransferContext> transferContextQueue = transferStation.getTransferContextQueue();
if (transferContextQueue.size() > transferStation.capacity) {
throw new RuntimeException("队列已经满了!");
}
CompletableFuture<R> future = new CompletableFuture<>();
boolean offer = transferContextQueue.offer(new TransferContext(UUID.randomUUID().toString(), param, future));
if (!offer) {
throw new RuntimeException("队列已经满了~");
}
return future.get(3, TimeUnit.SECONDS);
}
/**
* <p>封装返回结果</p>
* 业务端务必实现该接口完成,并将远端返回的响应结果封装到TransferContext#data中
* 并将TransferContext返回
* 默认方法中的作为实例
*
* @param transferContexts 请求上下文
* @return {@link List<TransferContext>}
* @throws Exception
*/
default List<TransferContext> invokeRemote(List<TransferContext> transferContexts) throws Exception {
if (CollectionUtils.isEmpty(transferContexts)) {
return null;
}
Iterator<TransferContext> iterator = transferContexts.iterator();
while (iterator.hasNext()) {
TransferContext req = iterator.next();
if (req != null) {
// 填充数据
// req.setData(invoke(transferContexts));
Map<String, java.io.Serializable> map = new HashMap<>();
map.put("orderTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
map.put("orderMoney", (BigDecimal.valueOf((long) (Math.random() * 10000), 2)));
req.setData(map);
}
}
return transferContexts;
}
}
}
// 实现接口
@Service("OrderTransferService")
public class OrderTransferService<T, R> implements TransferStation.TransferService<T, R> {
@Autowired
private RemoteService remoteService;
// 初始化TransferStation
private final TransferStation transferStation = new TransferStation(100);
@Override
@PostConstruct
public void initScheduledPool() {
// todo 日志修改
System.out.println("初始化线程池子->>>>>>>>>>>>>>>>>>>>>>>-----------");
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
threadPool.scheduleAtFixedRate(new TransferStation.ScheduledTask(transferStation.getTransferContextQueue(), this)
, 100, 10, TimeUnit.MILLISECONDS);
}
@Override
public R doRequest(T param) throws Exception {
return baseRequest(param, transferStation);
}
@Override
public List<TransferStation.TransferContext> invokeRemote(List<TransferStation.TransferContext> transferContexts) throws Exception {
// todo 修改日志打印
System.out.println("handDataDefault:调用远端接口..........................................");
List<TransferStation.TransferContext> transferContextTemp = transferContexts;
if (CollectionUtils.isEmpty(transferContextTemp)) {
return null;
}
//
List<String> orderCodeList = transferContextTemp.stream().map(r -> String.valueOf(r.getParam())).collect(Collectors.toList());
// todo 这里调用远程接口批量查询
List<Map<String, Object>> remoteOrderList = remoteService.getOrderInfoByOrderCodeBatch2(orderCodeList);
if (CollectionUtils.isEmpty(remoteOrderList)) {
return null;
}
for (TransferStation.TransferContext request : transferContextTemp) {
for (Map<String, Object> resp : remoteOrderList) {
// 通过唯一字段进行匹配,将返回结果进行设置在TransferContext#data
if (resp.get("orderCode").equals(request.getParam())) {
request.setData(resp);
}
}
}
return transferContextTemp;
}
}
// 请求实例
@Autowired
private OrderTransferService<String, Map<String, Object>> service;
// 调用方法doRequest
public Map<String, Object> queryOrderBatch2(String orderCode) throws Exception {
return service.doRequest(orderCode);
}
本文介绍了一种基于CompletableFuture的异步支付方法及多线程优化方案,包括阻塞队列形式的实现与优化,提高了系统的并发处理能力。
608

被折叠的 条评论
为什么被折叠?



