前言:导师的一个小项目,需求是给两个高请求的接口做一下并发,博主半路出家,十分费劲的搞出了这个并发,但是后来有学弟突然发现了springboot里面内置了tomcat,本身就可以实现并发了,具体的原理和性能我还在看,但是感觉光从实现路径上来说比我这个要方便好多。
整体框架:
在原生springboot框架(controller层、entity层、mapper层、service层)的同级目录下(同不同级无所谓只要能访问到就行)加上bean文件夹和utils文件夹,用来放一些项目需要的工具类、其他类,这里我们主要是放线程池相关的类,如下图:
ResponesMsg类的重写:
写一个队列中消息传达格式的类放在utils文件夹下,类中主要定义了线程运行结束之后要传出的数据字段。比如我自己的项目中需要传出图1数据,图2是对应的代码:
从controller层开始看起:
@PostMapping("/verify")
public DeferredResult<ResponseMsg<String>> verifyUserInfo(@RequestBody Map<String,String> map) throws Exception {
DeferredResult<ResponseMsg<String>> result = new DeferredResult<>(OUT_OF_TIME, OUT_OF_TIME_RESULT);
result.onTimeout(() -> {
log.info("调用超时");
if(isOverTime==true)
isOverTime=false;
else
isOverTime=true;
});
result.onCompletion(() -> {
log.info("调用完成");
});
//并发,加锁
synchronized (taskQueue) {
taskQueue.put(result,map);
}
log.info("接收任务线程完成并退出");
return result;
}
如上述代码,
@PostMapping用来声明接口的url路径。
DeferredResult<ResponseMsg>表示函数是有DeferredResult类型的返回值。(@RequestBody Map<String,String> map)代表POST方法请求时传入的参数 也就是http body里的内容。
- 先实例化一个DeferredResult类对象,然后调用DeferredResult类方法(同时也是回调函数):onTimeout()、onCompletion()。
- 然后并发加锁进行线程任务的接受,这里很好理解,多线程的每个线程之间是并发的,但是在主函数中,每个线程任务的开启一定都是串行的。这里有一个重点,也就是接受任务的时候,taskQueue类是我们自定义的线程任务队列类,其中的put方法也是自己写的,我这里因为本次调用是POST的需要传参数到线程内部进行操作,因此put函数里除了把消息体传进去,还把map参数也传进去了。
具体TaskQueue类:
@Component
public class TaskQueue {
private static final Logger log = LoggerFactory.getLogger(TaskQueue.class);
private static final int QUEUE_LENGTH = 2000;
private BlockingQueue<