背景:公司的项目,自己写了一个接口的时候,请求接口的具体service涉及到异步A+同步B的情况,需要等到同步B方法执行完成之后才会释放资源,因此如何控制好并发是一个问题
1. 解决思路
使用队列进行控制
2. 思路:
- 分析出真正会并发的一块代码
- 将真正会并发的那一块代码抽取出来,单独封装一个方法
- 将调用并发代码之前的方法A加锁,保证该方法A不会出现并发情况
- 在方法A中使用一个队列将需要执行的任务进行管理
- 当有第一个请求进入的时候,此时list为空,那么直接执行并发方法,如果当list不为空,那么将任务添加进去即可。
- 最后当第一个请求执行完成需要释放资源的时候,此时将执行的任务移除,判断list中是否有内容,如果有,取出list首位,并执行并发的方法。
3. 具体代码
第一步:等待编译回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @PostMapping("/apk/{mode}") public Result jenkinsCompile(@RequestBody RobustReq robustReq, @PathVariable("mode")Integer mode) { compileRecordService.saveParamAndStartCompile(robustReq.getLiTaskId(), robustReq, mode, new IJenkinsResultCallback() { @Override public void onResult(String taskId, boolean isSuccess) { if (isSuccess) { robustService.savRobustParam(taskId, robustReq); robustService.noticeInstall(taskId); } } }, TaskTypeEnum.ROBUST_TEST.getTaskCode());
return Result.ok(); }
|
第二步:回调完成,安装APK
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public synchronized void noticeInstall(String taskId) { if (taskIdList.isEmpty()) { exeInstall(taskId); } else { taskIdList.add(taskId); } }
private void exeInstall(String taskId) { List<Map<String, Object>> envInfoList = getAvaInfoList(rowList);
while (envInfoList.isEmpty()) { Random random = new Random(); int delay = random.nextInt(5 * 60 * 1000) + 60 * 1000;
try { Thread.sleep(delay); } catch (InterruptedException e) { e.printStackTrace(); } envInfoList = getAvaInfoList(rowList); }
Map<String, Object> envInfo = envInfoList.get(0); List<String> devicesList = (List<String>) envInfo.get("deviceIds"); String deviceId = devicesList.get(0);
Integer id = (Integer) envInfo.get("id");
String installUrl = Constants.Win.ADDRESS + Constants.Common.COLON + Constants.Win.JAVA_PORT + Constants.Common.SEPARATOR + Constants.Win.INSTALL_APK_HMI; HttpUtil.createPost(installUrl) .header("Content-Type", "application/json") .body(JSONUtil.toJsonStr(paramMap)) .execute(); }
|
第三步:等待另一台服务的响应:
1 2 3 4 5 6 7 8 9 10 11
| @PostMapping("/callback") public Result installCallback(@RequestBody InstallResp resp) { String taskId = resp.getTaskId();
if (resp.isSuccess()) { robustService.startRobust(taskId, infoMap -> { }, emitter); return Result.ok();
} }
|
第四步:执行任务
1 2 3 4 5
| public void startRobust(String taskId, ILiATCallback callback, ObservableEmitter<Boolean> emitter) { executeTask(runTime, returnNum, liTaskId, taskId);
startIntervalGetRate(liTaskId, taskId, emitter); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| private void executeTask(Integer runtime, Integer returnNum, Integer liTaskId, String taskId) { List<Map<String, Object>> envList = new ArrayList<>();
Map<String, Object> paramMap = new HashMap<>();
HttpResponse response = HttpUtil.createPost("xxx") .header("content-type", "application/json") .header("authorization", Constants.LiAT.AUTHORIZATION) .body(JSONUtil.toJsonStr(paramMap)) .execute();
taskIdList.remove(taskId); if (!taskIdList.isEmpty()) { String nextTaskId = taskIdList.get(0); exeInstall(nextTaskId); } }
|