AnyLogic随机分配服务逻辑异常:par_allowForGym为false时的循环问题
问题排查:随机分配服务的循环异常问题
代码功能说明
这段代码用于从wait队列释放首个元素,当服务存在剩余空间时,按随机规则将其分配至simulator或Gym服务。若生成的随机数无法匹配有效服务,最多重试生成100次随机数后退出循环。
代码实现
if (wait.size() > 1 && (simulators.size() < 6 || Gym.size() < 15)) { // Free the current wait and pick a service at random wait.free(wait.get(0)); Random rand = new Random(); int iterations = 0; while (true) { int randomNum = rand.nextInt(2) + 1; if (randomNum == 1 && simulators.size() < 6) { // Choose the simulator service if there's space available wait.get(0).var_simulatorService = true; break; } else if (randomNum == 2 && Gym.size() < 15 && wait.get(0).par_allowForGym == true) { // Choose the gym service if there's space available wait.get(0).var_Gym = true; traceln("The agent number " + wait.get(0)+ " Alllow to go Gym - " + wait.get(0).par_allowForGym); break; } else { // generate a new random number if the previous one didn't lead to a valid service iterations++; if (iterations >= 100) { traceln("The agent number " + wait.get(0)+ " Alllow to go Gym - " + wait.get(0).par_allowForGym); break; } } } }
问题描述
按照代码逻辑,当wait.get(0).par_allowForGym == false时,循环应持续生成随机数直到得到值1,否则最多执行100次后退出。但实际出现异常:循环未等到随机值为1就直接终止,需排查该问题原因。
相关截图


问题原因分析
- 外层判断与循环内状态不一致:外层的
(simulators.size() < 6 || Gym.size() < 15)仅在进入代码块时执行一次。如果在循环过程中simulators服务被其他操作占满(size达到6),后续生成随机数1时,simulators.size() <6的条件不再满足,会直接进入else分支累加次数,直到100次后退出。 - 提前释放队列元素导致的异常:代码先执行
wait.free(wait.get(0)),这会将队列首个元素从wait队列中移除,后续wait.get(0)可能指向队列的下一个元素,或者返回无效对象,导致par_allowForGym等属性的判断逻辑失效,循环提前终止。 - 无效重试的逻辑漏洞:当
par_allowForGym == false且simulators服务已满时,生成的随机数无论是1还是2都无法匹配有效分支,此时循环会直接进入重试计数,直到100次后强制退出,这与预期的“持续等待随机值1”逻辑不符。
修复建议
- 调整队列元素释放时机:将
wait.free(wait.get(0))移至服务分配完成后的break之前,确保在整个分配逻辑中,wait.get(0)始终指向目标元素。 - 优化循环内的服务可用性检查:在每次循环时重新确认可用服务,或者提前筛选出当前可用的服务列表,直接从可用列表中随机选择,避免无效的随机数生成。例如:
// 提前获取可用服务选项 List<Integer> availableServices = new ArrayList<>(); if (simulators.size() <6) availableServices.add(1); if (Gym.size()<15 && wait.get(0).par_allowForGym) availableServices.add(2); // 从可用选项中随机选择 if (!availableServices.isEmpty()) { int randomIndex = rand.nextInt(availableServices.size()); int selected = availableServices.get(randomIndex); if (selected ==1) { wait.get(0).var_simulatorService = true; } else { wait.get(0).var_Gym = true; traceln("The agent number " + wait.get(0)+ " Alllow to go Gym - " + wait.get(0).par_allowForGym); } wait.free(wait.get(0)); } - 强化外层进入条件:将外层判断改为
wait.size()>1 && (simulators.size()<6 || (Gym.size()<15 && wait.get(0).par_allowForGym)),确保进入代码块时至少有一个服务可分配,避免进入循环后无有效选项的情况。
内容的提问来源于stack exchange,提问作者Aqeel Tariq
相关产品推荐
相关产品推荐

