spingboot 并发请求下排队一个个"就诊"
有一个需求:编写一个接口 这个接口打开本地的notepad记事本,允许并发
如果单纯的写一个接口,并发下是会有问题的,因为notepad已经被第一个请求先打开了,后续请求都返回失败,如果我想每个请求都能打开成功,notepad被别的请求打开了那就阻塞等待直到关闭notepad。
类似医生一次就诊一个病人,病人抽号排队看病。
技术实现
阻塞队列+单例线程池
代码如下
实现Callable接口,这个接口有返回值
核心代码
package com.bim.task;
import com.bim.pojo.ConvertObj;
import com.bim.service.TransServiceImpl;
import com.bim.utils.Result;
import com.bim.utils.SpringUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.*;
/**
* @author gaoye
* @date 2022/2/16 11:50
* @desc 远程启动
*/
@Data
@Slf4j
public class StartTask implements Callable<Result> {
# 1.阻塞队列 一次一个任务
public static LinkedBlockingDeque<ConvertObj> linkBlockQueue = new LinkedBlockingDeque<>(1);
public StartTask(ConvertObj convertObj) {
try {
#2. put的时候 容量满了就阻塞 我设置了1个实现了排队进行
linkBlockQueue.put(convertObj);
log.info("当前队列值数量:" + linkBlockQueue.size());
} catch (InterruptedException e) {
log.info(e.getMessage());
}
}
@Override
public Result call() {
Result result;
try {
#3. submit后会执行我的业务
TransServiceImpl transService = SpringUtils.getBean("transServiceImpl");
#读取入栈的值 但没移除掉
ConvertObj convertObj = linkBlockQueue.peek();
#执行业务逻辑
result = transService.convert(convertObj.getHttpServl etRequest(), convertObj.getMultipartFile());
# 4. 移除队列首值也是唯一的值 被阻塞的请求可以put了 也就是第2步骤可以跑了
linkBlockQueue.take();
} catch (Exception e) {
try {
# 抛出异常也要去除掉,要不然以后没法put进去 服务就废了
linkBlockQueue.take();
} catch (InterruptedException ex) {
log.info(ex.getMessage());
}
log.error(e.getMessage());
return Result.fail(e.getMessage());
}
return result;
}
}
提交任务
#单例线程池
public static final ExecutorService threadPool = Executors.newSingleThreadExecutor();
#提交任务
StartTask startTask=new StartTask(convertObj);
Future<Result> future = threadPool.submit(startTask);
Result result = future.get();
如果你有更好的方法,请留言 或加qq:1129174385