Anylogic:如何将基于队列长度的叉车调度改为等待时间触发模式?
AnyLogic基于等待时间的叉车调度实现(替代队列长度阈值)
实现思路
不用timeout块触发的核心是:主动监控队列中卡车的等待时长,通过周期性检查或事件触发调整叉车资源池容量,卡车全程留在seize队列中,不会额外增加等待时间。
具体实现步骤
1. 给卡车代理添加等待时间记录变量
在你的卡车代理(如Truck类)中添加一个公共变量,用于记录卡车进入seize队列的时间:
public double enterWaitTime; // 记录进入等待队列的时间
2. 在seize块的「on enter」事件中记录进入时间
当卡车进入seize块的等待队列时,立即记录当前模型时间:
// 强制转换为你的卡车代理类型,记录进入队列的时间 ((Truck)agent).enterWaitTime = time();
3. 创建周期性检查事件
在模型中添加一个周期性事件(比如命名为checkWaitTimeout),设置合适的检查间隔(比如30秒,可根据模型精度调整),在事件中编写以下代码:
// 获取滑块设置的等待超时阈值(假设滑块单位为分钟,模型时间单位一致) double waitThreshold = (double)TruckWaitTimeSlider.getValue(); // 获取当前叉车资源池的容量 int currentCapacity = worker1.get_capacity(); // 标记是否需要调度额外叉车 boolean triggerExtraForklift = false; // 遍历seize队列中的所有卡车,检查等待时长 for(int i = 0; i < seizeWorker1.size(); i++){ Truck truck = (Truck)seizeWorker1.get(i); // 计算当前等待时长:当前时间 - 进入队列时间 double currentWaitTime = time() - truck.enterWaitTime; // 只要有一辆卡车等待超时,就触发调度 if(currentWaitTime > waitThreshold){ triggerExtraForklift = true; break; // 无需继续检查其他卡车 } } // 如果触发调度,且当前容量未达到上限,调整叉车数量 if(triggerExtraForklift && currentCapacity < (int)ForkliftThresholdMax.getValue() + ForkliftSchedule.getValue(time())){ // 方式1:每次增加1辆叉车(按需调整) worker1.set_capacity(currentCapacity + 1); // 方式2:直接设置到最大允许容量(和原逻辑一致) // worker1.set_capacity((int)ForkliftThresholdMax.getValue() + ForkliftSchedule.getValue(time())); }
4. 可选:超时后恢复初始容量(按需配置)
如果需要在队列清空后恢复叉车初始容量,可以在seize块的「on release」事件中添加代码:
// 当队列中无等待卡车时,恢复叉车初始容量 if(seizeWorker1.size() == 0){ // 这里的初始容量替换为你的基础调度值,比如原ForkliftSchedule的当前值 worker1.set_capacity(ForkliftSchedule.getValue(time())); }
关键说明
- 这种方式不会让卡车离开
seize队列,完全避免了timeout块导致的等待时间延长问题 - 检查间隔可根据模型需求调整:间隔越小,触发越及时,但会增加模型计算量;间隔越大,延迟越高,但性能开销小
- 可以根据需求优化触发逻辑:比如只有当容量未达到上限时才触发,或者设置触发标志避免重复调整
内容的提问来源于stack exchange,提问作者Terence14
相关产品推荐
相关产品推荐

