OO课程第二次作业电梯

目录

文件结构

多线程的协同和同步控制

功能设计和性能设计

程序结构与面向对象

三次作业遇到的BUG

心得体会

文件结构

| .gitignore
| hw2.iml
| pom.xml
|
+---course
| elevator-input.jar
| timable-output.jar
|
+---src
| +---main
| | +---java
| | | | Main.java
| | | | Tester.java
| | | |
| | | +---building
| | | | Bridge.java
| | | | Building.java
| | | |
| | | +---elevator
| | | | Driver.java
| | | | Elevator.java
| | | | ElevatorElementPath.java
| | | |
| | | +---goods
| | | | Goods.java
| | | | GoodsStage.java
| | | |
| | | +---interfaces
| | | | BuildingInterface.java
| | | | Callback.java
| | | | DriverInterface.java
| | | | ElevatorInterface.java
| | | | PlanInterface.java
| | | |
| | | +---scheduler
| | | | MinPath.java
| | | | NeedStop.java
| | | | PlanHelper.java
| | | | Scheduler.java
| | | |
| | | \---utils
| | | Helper.java
| | | MyReq.java
| | | Timer.java
| | |
| | \---resources
| \---test
| \---java
+---testIn
| in1
| in2
| in3
|
\---testOut
out1
out2
out3

 

多线程的协同和同步控制

本次作业主要有Main,Scheduler,CallbackHelper,Driver四种进程。Callback是为了鲁棒性设计的,在每个Driver进程自然结束时调用。其他的比较好理解,Main启动Scheduler,Scheduler启动Driver。

//Scheduler
@Override
public void callback() { new Thread(this::startNew, "callback start helper of " + Thread.currentThread().getName()).start(); }

在新人到来时立即尽快结束所有Driver,Scheduler重新规划。

//Driver
@Override
public void run() { Helper.print(getName() + " start running"); for (ElevatorElementPath p : path) { if (stop) { ele.stop(); return; } switch (p) { 。。。 } if (stop) { ele.stop(); return; } if (p == ElevatorElementPath.OPEN) { break; } } call.callback(); } @Override public void tryStop() { stop = true; }

同步控制上所有集合全部进行了上锁,部分基本类型进行了封装。

public class NeedStop {
    private int waiting = 0;

    synchronized int add() {
        return ++waiting;
    }

    synchronized int del() {
        return --waiting;
    }

    synchronized boolean can() {
        Helper.myAssert(waiting > 0, "impossible waiting val");
        return waiting == 1;
    }
}

 

功能设计与性能设计

功能设计上,我使用静态确定人的路径,动态确定电梯路径。人的路径由MinPath规划(实现了spfa求最短路),电梯路径由Scheduler规划(原则是每个方向上第一个电梯先取,先取位置最远的并且方向是这个方向的人),规划结果存储在PlanHelper中。

安全性上,由于每个类功能很专一所以自认为做的很好,建立了Bridge进行人的交换,而Elevator保证了电梯运行不会出逻辑错误。

性能上由于是随机数据,所以只要电梯差得开,加LOOK算法,就可以踩到时间下限(一个电梯是最后到达的人的时间+电梯上下总时间),事实上如果过度优化一般连这个都达不到。

(红色是进,绿色是出,第二次的middle6,自己写的绘电梯运行图工具)

本次作业我的可拓展性也很好,尤其是算法我的解耦很好,能够比较好的适应策略的更换。countForInEle,countForInBud1,countForInBud2,(参数包括电梯,楼信息,待规划人集合)分别实现了对电梯内,楼里的人的多种路径规划方式。而main中则是策略的设计界面,通过对上面的函数的简单堆砌就可以描述出你想要的策略。

程序结构与面向对象

 

class 

OCavg WMC

main.java.building.Bridge

1.7692307692307692 23.0
main.java.building.Building 1.5 9.0
main.java.elevator.Driver 3.5 14.0
main.java.elevator.Elevator 1.65 33.0
main.java.elevator.ElevatorElementPath   0.0
main.java.goods.Goods 1.125 9.0
main.java.goods.GoodsStage 1.0 3.0
main.java.Main 7.0 7.0
main.java.scheduler.MinPath 2.076923076923077 27.0
main.java.scheduler.NeedStop 1.0 3.0
main.java.scheduler.PlanHelper 1.2 12.0
main.java.scheduler.Scheduler 2.4285714285714284 68.0
main.java.Tester 3.0 9.0
main.java.utils.Helper 1.8125 29.0
main.java.utils.MyReq 1.25 10.0
main.java.utils.Timer 1.7142857142857142 12.0
Total   268.0
Average 1.8741258741258742 16.75

可以看到设计的是非常优秀的。相比于很多同学,我完全没有出现循环依赖。这是充分利用了接口的结果。

类的复杂度也比较的低。其中Bridge的设计分散了elevator,和building的功能我觉得很成功。

缺点就是类之间的依赖程度还是比较高的,当时没有关注这方面的解耦。

三次遇到的BUG

三次互测均没有被测出bug。

第二次强测出现了人没有被处理的情况。原来是map线程不安全,导致人没有被加到考虑集中。

编程时在多线程上我遇到过一次死锁。原来是我的scheduler在定策略时会锁住自己并暂停Driver,没有callbackhelper,有的Driver也会走到callback定策略这最后一步,由于无法获得锁,程序死锁。

心得体会

这次作业花费了比较大的心思做架构和优化设计。架构因此比求导好了很多。但我仍认为还有很大空间,并得到一个经验:不会划分功能,就别瞎划分。优化走了很多弯路,最后悟出没有实验就没有发言权,遂把电梯路径画了出来,最终自认为摸到了真理(因为指导书说了是随机数据,分散+LOOK就是最优),可惜没有心力去实现了。

最后遗憾就是maven的架子都搭好了,但还是没时间做测试。

posted @ 2020-04-18 11:51  woafrnraetns  阅读(154)  评论(0编辑  收藏  举报