BUAA-2026-OO U2总结

李欣桐-24373274 2026-04-23 21:24:12

程序结构整体分析

架构展示

整体沿用分层的生产者-消费者的设计:

输入线程 - 分配器线程 - 电梯线程
(显然,输入/分配需求/电梯运行是三种并行的线程,这样的设计是很自然的)

img

复杂度

  • Class Metrics

    ClassOCavgOCmaxWMC
    Average1.843.4810.05
    tools.Elevator1.636.085.0
    strategy.NormalPolicy2.95.052.0
    • 分析可知,代码整体没有很复杂的方法,但部分类WMC过大,反映出其负担过大成为巨类的问题
      • Elevator 的 WMC 明显偏高,主要原因是它同时承担了电梯实体状态、基础动作、乘客进出、特殊流程和输出封装等职责。随着第二、三次迭代引入检修、改造、回收,特殊状态流程也继续堆叠在该类中,导致其逐渐演化为巨类。

待改进缺点

  • Elevator类负担太大,长度过长
    • 可能可以引入设计模式来优化,但是迭代时为了避免重构没有尝试

架构设计体验与优化

第一次作业

基本是照搬oolens上的设计思路,采用分层生产者-消费者设计,电梯运行策略使用LOOK策略

  • 本次作业不涉及dispatch,但为了后续的迭代仍预留了DispatchThread和DispatchStrategy

第二次作业

调度设计

选择自由竞争策略,设计了一个代价公式(理论上应该多试几组参数但现在的参数效果还不错)

private int calculateCost(ElevatorStatus status, PersonRequest request) {
    int currentFloor = status.getCurrentFloorIndex();
    int fromFloor = FloorUtil.toIndex(request.getFromFloor());
    
    int distanceCost = Math.abs(currentFloor - fromFloor);
    int directionCost = calculateDirectionCost(status, request);
    int waitingCost = status.getWaitingCount() * 2;
    int loadCost = status.getCurrentWeight() / 100;
    
    return distanceCost + directionCost + waitingCost + loadCost;
}
  • 优化:为避免少数可用电梯被瞬间塞入过多任务,在可用电梯数量较少且候选电梯等待队列超过阈值时,调度器会暂缓接收,将请求放回全局队列稍后重试。

第三次作业

调度设计

在第二次作业的基础上,新增了跨区运输的需求。

核心:分区运输怎么实现?

  1. 添加TransferRegistry,用以记录跨区PersonRequest的最终目的地
    由DispatchThread和12个ElevatorThread共享
    • DispatchThread:注册跨区乘客最终目的地
    • ElevatorThread:乘客下车时查询 finalToFloor,并在最终到达时清理
  2. 策略:对于一个请求
    1. 原请求有人能接:直接派原请求。
    2. 原请求没人能接,且它跨区:尝试拆成 from -> F2。
    3. 第一段有人能接:派第一段,并登记最终目的地。
    4. 第一段也没人能接:返回 -1,稍后重试。

线程安全设计

  • 共享对象均使用 synchronized 封装访问,通过 wait/notifyAll 实现生产者-消费者协作。
  • 电梯状态通过 ElevatorStatus 向调度器暴露,只提供必要的只读快照信息,避免调度器直接操作电梯内部状态。
  • 双轿厢的井道约束集中在 ShaftStatus 中处理,避免两个电梯线程各自判断导致约束分散。

bug分析

第二次互测中,受到hack数据:
在同一时间,五台电梯全部收到维修请求;在它们进行维修时,涌入大量PersonRequest

  • 问题分析:我的电梯没有设计延迟接收请求,于是大量Request一次性被仅剩的一台Normal电梯接收,后续无法由其它电梯分摊压力,系统退化成单电梯,最后导致超时。
  • 解决:设计延迟接收,当一台电梯对应的assignedTaskQueue内Request数量到达设定的阈值,停止接收Request

第三次迭代中,如果进入双轿厢模式后,主轿厢结束委托时刚好停在换乘层,但备用车厢有接到了需要移动到换乘层的request,就会造成死锁

  • 解决:添加自动让位机制

第三次迭代中出现双轿厢碰撞的问题

  • 问题分析:对于不能同层的约束不够准确,只是通过判断对方现层数来决定自己是否移动,因此可能出现刚好一起移动到换乘层的情况
  • 解决:预占目标楼层

大模型使用

  • 在第一次迭代时,我对于如何让DispatchStrategy获得电梯状态感到迷惑,于是先尝试和大模型交流。结果它一直教我到处开快照,试图把架构改得面目全非,于是最后还是自己设计了同步方法。
  • 但是,大模型在帮忙简化代码的方面给了我很大帮助,在它的帮助下我把超出checkstyle要求行数的类与方法成功优化为合法行数
    • 后续如果想引入设计模式来继续优化,感觉也可以让大模型提供帮助
  • 另外,大模型提高了debug的效率。手动找output中不合题意的部分是件很费眼的工作,然而大模型对于这种有明确规则的工作非常拿手。

心得体会

  • 互测其实是很好地学习他人思路的机会,在寻找他人代码漏洞的同时,自己也拓展了题目的实现思路
  • 第二单元作业后期与os课程中的进程同步互斥知识学习同时进行,学习时感觉有相辅相成之感
...全文
216 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

307

社区成员

发帖
与我相关
我的任务
社区描述
2026年北航面向对象设计与构造
java 高校
社区管理员
  • 孙琦航
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧