整体思路:
1.多用户并发请求后端接口;
2.后端会启动多个线程处理前端的请求,如果并发很大就会对后端数据库造成很大的并发压力;
3.通过 JAVA 队列把用户的并发请求转换为串行批量操作数据库;
4.在 JAVA 应用中设置一个存储所有请求数据的 JAVA 队列(每一个 JAVA 应用进程会有一个这样的队列),进行数据批量入库的线程会从该队列批量获取数据进行入库;
5.在 JAVA 应用中设置一个队列数组,进行数据批量入库的线程会在完成一批入库后,把各针对各请求处理线程的响应数据写入各请求处理线程对应的队列,每个处理请求的线程会使用其中的一个队列获取数据库入库完成后的响应消息;
6.请求处理线程获得数据库入库完成的响应消息后返回响应给前端;
package com.sande.user.thread;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class SyncMap {
private static ConcurrentHashMap<String,BlockingQueue> queueMap = new ConcurrentHashMap<>();
public static BlockingQueue<String> queue = new ArrayBlockingQueue<String>(100);
public static void setQueueMap(String uuid,BlockingQueue queue) {
queueMap.put(uuid, queue);
}
public static BlockingQueue getQueueMap(String uuid) {
return queueMap.get(uuid);
}
}
package com.sande.user.trade.serviceImpl;
import javax.annotation.Resource;
import com.sande.user.thread.SyncMap;
@Service(value = "tradeServiceQueueImpl")
public class TradeServiceQueueImpl {
public void addQueue() throws InterruptedException {
BlockingQueue<String> queue2 = new ArrayBlockingQueue<String>(3);
SyncMap.setQueueMap("queue2", queue2);
SyncMap.queue.offer("test addQueue");
System.out.println(queue2.take());
}
}
package com.sande.user.trade.controller;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.sande.user.trade.dao.TradeMessage;
import com.sande.user.trade.service.TradeService;
import com.sande.user.trade.serviceImpl.TradeServiceQueueImpl;
@RestController
@RequestMapping(value="/trade")
public class TradeController {
@Autowired
@Qualifier(value="tradeServiceQueueImpl")
private TradeServiceQueueImpl tradeServiceQueue;
@RequestMapping(value="/order3",method= {RequestMethod.GET , RequestMethod.POST})
public TradeMessage order3() {
String message="test";
TradeMessage tradeMessage=null;
//tradeMessage = tradeServiceQueue.trade(message);
try {
tradeServiceQueue.addQueue();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/* System.out.println("controller uuid:"+ tradeMessage.getUuid());
System.out.println("controller message:"+ tradeMessage.getMessage());*/
return tradeMessage;
//return "完成";
}
}
应用启动时,自动执行的从队列批量消费消息的后台任务。
逻辑:循环从队列获取数据,假设每100条数据为一个批次,当提取完100条数据后进行批量入库。或者队列中数据不足100条,从队列获取数据返回空时进行批量入库。如果一个批次在队列中一条数据也没获取到就调用队列的 task 方法阻塞线程,等有消息时再唤醒线程。
package com.sande.user.trade.serviceImpl;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;
import com.sande.user.thread.SyncMap;
@Service
public class QueueServiceImpl implements ApplicationRunner {
//public void consumeQueue() {
//}
@Override
public void run(ApplicationArguments args) throws Exception {
// TODO Auto-generated method stub
String string = new String();
try {
string =SyncMap.queue.take();
SyncMap.getQueueMap("queue2").offer(string);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}