Java编程技巧-并发处理-01

背景:公司的项目,自己写了一个接口的时候,请求接口的具体service涉及到异步A+同步B的情况,需要等到同步B方法执行完成之后才会释放资源,因此如何控制好并发是一个问题

1. 解决思路

使用队列进行控制

2. 思路:

  1. 分析出真正会并发的一块代码
  2. 将真正会并发的那一块代码抽取出来,单独封装一个方法
  3. 将调用并发代码之前的方法A加锁,保证该方法A不会出现并发情况
  4. 在方法A中使用一个队列将需要执行的任务进行管理
  5. 当有第一个请求进入的时候,此时list为空,那么直接执行并发方法,如果当list不为空,那么将任务添加进去即可。
  6. 最后当第一个请求执行完成需要释放资源的时候,此时将执行的任务移除,判断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);

// 1~5min
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);
}
}

Java编程技巧-并发处理-01
https://baijianglai.cn/Java编程技巧-并发处理-01/156a7266de3c/
作者
Lai Baijiang
发布于
2024年2月1日
许可协议