菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
450
0

OO第二单元总结

原创
05/13 14:22
阅读数 40614

OO第二单元总结

基于度量分析程序

第五次作业

类图分析及设计策略

​ 在本次作业中采用生产者-消费者模型,共有七个类,在MainClass中启动InputRequest线程和Controller线程,RequestList作为共享对象,InputRequest作为生产者添加新的RequestRequestListController作为消费者从RequestList中获取Request。同时,Controller类中维护一个队列waitList,适时添加新的RequestRequestList
​ 调度算法采取了Look算法,若新的Request与电梯方向一致,并且上行时出发楼层比电梯现在楼层高,下行时出发楼层比现在楼层低,则可进入requestList,否则进入等待队列waitList。将电梯本次上行或下行所需到达楼层用floorSet存储,调用floor()方法或ceiling()方法即可得到电梯下一个需要到达的楼层,到达楼层后Controller发送指令给Elevator,根据Elevator内部的inElevatorList上人或下人。当到达该方向最高或最低楼层后,变换方向,将waitList中方向一致的Request都加入requestList,并抵达这次上行(下行)的最低(最高)楼层。大部分调度均由Controller类完成。
​ 没有输入时Controller await(),改WorkState为Waiting,有新的RequestsignalAll(),改WorkState为Running。当输入结束后,改WorkState为Stop,Controller检测到Stop并且ArrayList均为空时,结束Controller进程。

时序图

代码复杂度分析

Method ev(G) iv(G) v(G)
unitwo.Controller.Controller(RequestList,Elevator) 1 1 1
unitwo.Controller.addSubFloor() 2 1 2
unitwo.Controller.addWaitList(Request) 1 1 1
unitwo.Controller.awaitController() 1 1 2
unitwo.Controller.changeDirection() 1 5 7
unitwo.Controller.comeInElevator(int,Boolean) 1 1 1
unitwo.Controller.comeOutElevator(int) 1 1 1
unitwo.Controller.getNowFloor() 1 1 1
unitwo.Controller.getWorkState() 1 1 1
unitwo.Controller.isUpdown() 1 1 1
unitwo.Controller.run() 6 12 15
unitwo.Controller.setStop() 1 1 1
unitwo.Controller.signalController() 1 1 1
unitwo.Controller.subWaitList() 2 3 4
unitwo.Elevator.Elevator() 1 1 1
unitwo.Elevator.arriveFloor(int) 1 1 1
unitwo.Elevator.closeDoor(int) 1 1 1
unitwo.Elevator.comeOnElevator(ArrayList) 1 1 1
unitwo.Elevator.comeOutElevator(int) 1 3 3
unitwo.Elevator.getSize() 1 1 1
unitwo.Elevator.openDoor(int) 1 1 1
unitwo.InputRequest.InputRequest(RequestList,Controller) 1 1 1
unitwo.InputRequest.run() 3 7 7
unitwo.MainClass.main(String[]) 1 1 1
unitwo.Request.Request(int,int,int) 1 1 2
unitwo.Request.compareTo(Request) 3 2 3
unitwo.Request.getInFloor() 1 1 1
unitwo.Request.getOutFloor() 1 1 1
unitwo.Request.inElevator() 1 1 1
unitwo.Request.outElevator() 1 1 1
unitwo.Request.whetherInElevator(int,Boolean) 2 1 3
unitwo.Request.whetherInSet(int,Boolean) 3 1 7
unitwo.Request.whetherInSetFW(int,Boolean) 3 1 5
unitwo.Request.whetherOutElevator(int) 2 1 2
unitwo.RequestList.RequestList(ArrayList) 1 1 1
unitwo.RequestList.cleanSet() 1 3 3
unitwo.RequestList.get(int,boolean) 1 3 3
unitwo.RequestList.getMaxMinFloor(Boolean) 3 3 3
unitwo.RequestList.getNextFloor(int,Boolean) 4 4 4
unitwo.RequestList.getSize() 1 1 1
unitwo.RequestList.put(Request) 1 1 1

​ 从上表可以看出,由于将许多调度都设计在了Controller进程的run()方法中,导致该方法复杂度较高,不利于后续作业扩展,同时在一些判断是否上电梯,是否进入requestList的方法中,判断语句较多,导致圈复杂度较高。

代码行数分析

Package Name Type Name Method Name LOC CC PC
unitwo Controller Controller 8 1 2
unitwo Controller addWaitList 3 1 1
unitwo Controller subWaitList 14 4 0
unitwo Controller getNowFloor 3 1 0
unitwo Controller isUpdown 3 1 0
unitwo Controller addSubFloor 8 2 0
unitwo Controller run 54 8 0
unitwo Controller setStop 3 1 0
unitwo Controller getWorkState 3 1 0
unitwo Controller awaitController 13 1 0
unitwo Controller signalController 10 1 0
unitwo Controller changeDirection 28 4 0
unitwo Controller comeInElevator 5 1 2
unitwo Controller comeOutElevator 3 1 1
unitwo Elevator Elevator 3 1 0
unitwo Elevator openDoor 3 1 1
unitwo Elevator closeDoor 3 1 1
unitwo Elevator arriveFloor 3 1 1
unitwo Elevator comeOnElevator 3 1 1
unitwo Elevator comeOutElevator 9 3 1
unitwo Elevator getSize 3 1 0
unitwo InputRequest InputRequest 4 1 2
unitwo InputRequest run 32 7 0
unitwo MainClass main 11 1 1
unitwo Request Request 11 2 3
unitwo Request getInFloor 3 1 0
unitwo Request getOutFloor 3 1 0
unitwo Request compareTo 11 3 1
unitwo Request whetherOutElevator 8 2 1
unitwo Request whetherInElevator 8 2 2
unitwo Request whetherInSet 11 3 2
unitwo Request whetherInSetFW 11 3 2
unitwo Request outElevator 3 1 0
unitwo Request inElevator 3 1 0
unitwo RequestList RequestList 4 1 1
unitwo RequestList put 5 1 1
unitwo RequestList get 12 3 2
unitwo RequestList getNextFloor 20 4 2
unitwo RequestList cleanSet 10 3 0
unitwo RequestList getMaxMinFloor 11 3 1
unitwo RequestList getSize 3 1 0

​ 从代码行数中也可以看出来两个进程的run()方法行数较多,复杂度高,不利于后续作业的扩展。

第六次作业

​ 第六次作业主要从单部电梯改为了多部电梯,增加了地下层并且为电梯增加了人数上限。

类图分析及设计策略

​ 在本次作业中采取Work Thread模式,共七个类。InputRequest类为委托者(Client),Controller类作为通道(Channel),Elevator类作为工人(Worker),Request类即为请求。Controller类作为共享对象,同时承担了大部分的调度责任,为每个Elevator分配合适的Request,并且数量不超过上限,Elevator只负责完成分配给他的请求。每个Elevator都实例化一个WaitList,管理分配给该电梯的乘客,进行电梯内部乘客进电梯和出电梯的调度。本次作业中还是只有InputRequest线程和Elevator线程。
​ 这次作业还是采取Look算法,因为大部分设计沿用了上次作业。如电梯改变方向、需到达楼层的计算等。但因为改为多部电梯,所以在Controller的调度,putRequest()方法中,若Request上(下)行,则在方向一致、未超载且现在楼层低(高)于上电梯的楼层的电梯中选择人数最少的一部电梯,添加入该部电梯所属的WaitList中维护的容器中,否则添加入Controller中的容器,等待下次分配。在这种调度算法下,分配给电梯的请求不会超过上限,并且能在一次上行或下行中全部完成。而Elevator除了与上次作业相同,会在电梯换方向时从Controller的未分配乘客中找到方向一致的Request分配给自己,还会在从满载到有人下电梯的时刻,从Controller的未分配中找到不超数量的合适的Request加入。
​ 当电梯完成所有分配给自己的请求并且Controller中没有未分配请求时await(),改WorkState为Waiting,有新的RequestsignalAll(),改WorkState为Running。当输入结束后,改WorkState为Stop,Elevator检测到Stop并且完成所有分配给自己的请求,Controller中也没有未分配请求时,结束Elevator进程。

时序图

代码复杂度分析

Method ev(G) iv(G) v(G)
unitwo.Controller.Controller(int) 1 1 2
unitwo.Controller.awaitElevator(int) 1 1 2
unitwo.Controller.getRequest(int,int,int,Boolean) 8 10 12
unitwo.Controller.getRequsetChange(boolean,int,int) 8 8 10
unitwo.Controller.getSize() 1 1 1
unitwo.Controller.putRequest(Request) 4 7 10
unitwo.Controller.setStop() 1 2 2
unitwo.Controller.signalElevator() 1 2 2
unitwo.Controller.startWork() 1 2 2
unitwo.Elevator.Elevator(char,Controller) 1 1 1
unitwo.Elevator.addRequest(Request) 1 1 1
unitwo.Elevator.addSubFloor() 2 1 2
unitwo.Elevator.arriveDestination() 1 3 3
unitwo.Elevator.arriveFloor(int) 1 1 2
unitwo.Elevator.changeDirection() 1 1 1
unitwo.Elevator.changeElevatorDirection() 1 5 7
unitwo.Elevator.changeUpdown() 1 1 1
unitwo.Elevator.closeDoor(int) 1 1 2
unitwo.Elevator.getElevatorState() 1 1 1
unitwo.Elevator.isUpdown() 1 1 1
unitwo.Elevator.openDoor(int) 1 1 2
unitwo.Elevator.run() 6 11 13
unitwo.Elevator.setElevatorState(ElevatorState) 1 1 1
unitwo.Elevator.whetherInSetBegin(Request) 1 8 9
unitwo.InputRequest.run() 3 4 6
unitwo.MainClass.main(String[]) 1 1 1
unitwo.Request.Request(int,int,int) 1 1 2
unitwo.Request.compareTo(Request) 4 1 4
unitwo.Request.equals(Object) 3 2 4
unitwo.Request.getId() 1 1 1
unitwo.Request.getInFloor() 1 1 1
unitwo.Request.getOutFloor() 1 1 1
unitwo.Request.hashCode() 1 1 1
unitwo.Request.inElevator(char) 1 1 2
unitwo.Request.isUpdown() 1 1 1
unitwo.Request.outElevator(char) 1 1 2
unitwo.Request.whetherInElevator(int,Boolean) 2 1 3
unitwo.Request.whetherOutElevator(int) 2 1 2
unitwo.WaitList.WaitList() 1 1 1
unitwo.WaitList.addRequest(Request,char) 1 1 1
unitwo.WaitList.cleanSet() 1 5 5
unitwo.WaitList.comInElevator(int,boolean,char) 1 3 3
unitwo.WaitList.comeOutElevator(int,char) 1 3 3
unitwo.WaitList.getCustomer() 1 1 1
unitwo.WaitList.getMaxMinFloor(Boolean) 3 3 3
unitwo.WaitList.getNextFloor(int,Boolean) 4 4 4

​ 上次作业进程的run()方法复杂度较高,本次作业中将Elevatorrun()方法拆分出一部分,与上次相比,复杂度有所降低,但因为一些关于是否await()和是否结束进程的判断都在run()方法中,所以复杂度还是较高。并且在调度器分配Request的几个方法中因为涉及到许多电梯状态以及Request成员变量的判断导致复杂度也较高。

代码行数分析

Package Name Type Name Method Name LOC CC PC
unitwo Controller Controller 12 2 1
unitwo Controller startWork 5 2 0
unitwo Controller putRequest 37 9 1
unitwo Controller getRequest 43 10 4
unitwo Controller awaitElevator 13 1 1
unitwo Controller signalElevator 12 2 0
unitwo Controller getRequsetChange 43 10 3
unitwo Controller getSize 3 1 0
unitwo Controller setStop 6 2 0
unitwo Elevator Elevator 11 1 2
unitwo Elevator addRequest 4 1 1
unitwo Elevator run 44 7 0
unitwo Elevator changeUpdown 3 1 0
unitwo Elevator arriveDestination 22 3 0
unitwo Elevator whetherInSetBegin 19 5 1
unitwo Elevator openDoor 7 2 1
unitwo Elevator closeDoor 7 2 1
unitwo Elevator arriveFloor 7 2 1
unitwo Elevator addSubFloor 8 2 0
unitwo Elevator changeDirection 7 1 0
unitwo Elevator changeElevatorDirection 26 4 0
unitwo Elevator setElevatorState 3 1 1
unitwo Elevator getElevatorState 3 1 0
unitwo Elevator isUpdown 3 1 0
unitwo InputRequest run 32 5 0
unitwo MainClass main 5 1 1
unitwo Request Request 11 2 3
unitwo Request getId 3 1 0
unitwo Request getInFloor 3 1 0
unitwo Request getOutFloor 3 1 0
unitwo Request isUpdown 3 1 0
unitwo Request equals 10 3 1
unitwo Request hashCode 3 1 0
unitwo Request compareTo 14 4 1
unitwo Request whetherOutElevator 8 2 1
unitwo Request whetherInElevator 8 2 2
unitwo Request outElevator 7 2 1
unitwo Request inElevator 7 2 1
unitwo WaitList WaitList 5 1 0
unitwo WaitList addRequest 11 1 2
unitwo WaitList getNextFloor 26 4 2
unitwo WaitList cleanSet 17 5 0
unitwo WaitList getMaxMinFloor 17 3 1
unitwo WaitList comInElevator 10 3 3
unitwo WaitList comeOutElevator 9 3 2
unitwo WaitList getCustomer 9 1 0

​ 从行数中也可看出,行数较多的也是复杂度较高的几个方法,如上述提到的Elevatorrun()方法和Controller中负责分配Request的几个方法。

第七次作业

​ 在本次作业中,将电梯分为三类,每类具有不同的停靠楼层、运行时间、载客量,并且可以动态增加各种类型的电梯。

类图分析及设计策略

​ 本次作业中有八个类,多数架构与上次作业相同,采取Work Thread模式。此外,Controller负责总调度,保证分配给每个电梯的Request是合适的(在一次上行或下行中可全部完成)且不超上限。Elevator仅需完成分配给自己的Request,每个Elevator拥有的ViceController负责管理分配给电梯的Request
​ 本次作业大体上依然是Look算法,只是增加了关于停靠楼层的调度,改变了一些判断条件。若Request可直达则不换乘,若需要换乘则在一开始便决定好换乘楼层,修改RequestoutFloor为换乘楼层,新增一个Request加入Controller新增的用于存储新产生RequestArrayList,即secondTravel中,当该Request完成后,从Controller中找到换乘新生成的Request,重新putRequest()。并且需换乘的Request会为第二次乘电梯所用的电梯设置一个TargetFloor,即为第二次乘电梯的上电梯楼层,若该电梯无分配的Request,则会抵达TargetFloor之后再await(),在Request频率低的时候,可节约换乘时间。同时,在调度的时候修改了判断条件,增加了是否可到达的条件。
​ 为动态增加电梯的需求在Controller类中增加了addElevator()方法,在电梯创建时即设置好载客量、运行时间等。同时修改了电梯线程结束的条件,其余设计几乎不变。

时序图

代码复杂度分析

Method ev(G) iv(G) v(G)
unitwo.Controller.Controller() 1 1 1
unitwo.Controller.addElevator(String,String) 1 2 3
unitwo.Controller.awaitElevator(int) 1 2 3
unitwo.Controller.getRequest(int,int,int,Boolean) 8 8 10
unitwo.Controller.getRequsetChange(boolean,int,int) 8 8 10
unitwo.Controller.getSize() 1 1 1
unitwo.Controller.getTransferFloor(Request) 1 7 11
unitwo.Controller.needTransfer(Request) 1 3 3
unitwo.Controller.putRequest(Request) 1 2 2
unitwo.Controller.secondPutRequest(Request) 3 3 3
unitwo.Controller.setStop() 1 2 2
unitwo.Controller.setTarget(Request) 4 4 4
unitwo.Controller.signalElevator() 1 3 3
unitwo.Controller.startWork() 1 2 2
unitwo.Controller.throughRequest(Request) 4 8 11
unitwo.Elevator.Elevator(String,Controller,int[],int,int,int) 1 1 1
unitwo.Elevator.addRequest(Request) 1 1 1
unitwo.Elevator.addSubFloor() 2 1 2
unitwo.Elevator.arriveDestination() 1 3 3
unitwo.Elevator.arriveFloor(int) 1 1 2
unitwo.Elevator.changeDirection() 1 1 1
unitwo.Elevator.changeElevatorDirection() 1 5 7
unitwo.Elevator.changeUpdown() 1 1 1
unitwo.Elevator.closeDoor(int) 1 1 2
unitwo.Elevator.getElevatorState() 1 1 1
unitwo.Elevator.isUpdown() 1 1 1
unitwo.Elevator.openDoor(int) 1 1 2
unitwo.Elevator.run() 7 11 14
unitwo.Elevator.setElevatorState(ElevatorState) 1 1 1
unitwo.Elevator.setTargetFloor(int) 1 1 1
unitwo.Elevator.toTargetFloor() 4 4 7
unitwo.Elevator.whetherAvailable(Request) 2 1 3
unitwo.Elevator.whetherGetRequest(Request) 3 10 11
unitwo.Elevator.whetherGetRequestChange(Request) 2 3 4
unitwo.Elevator.whetherInSetBegin(Request) 1 10 11
unitwo.InputRequest.run() 3 6 8
unitwo.MainClass.main(String[]) 1 1 1
unitwo.Request.Request(int,int,int,boolean,boolean) 1 1 2
unitwo.Request.getFinalFloor() 1 1 1
unitwo.Request.getId() 1 1 1
unitwo.Request.getInFloor() 1 1 1
unitwo.Request.getOutFloor() 1 1 1
unitwo.Request.inElevator(String) 1 1 2
unitwo.Request.isFirstTravel() 1 1 1
unitwo.Request.isReady() 1 1 1
unitwo.Request.isTransfer() 1 1 1
unitwo.Request.isUpdown() 1 1 1
unitwo.Request.outElevator(String) 1 1 2
unitwo.Request.setFinalFloor(int) 1 1 1
unitwo.Request.setOutFloor(int) 1 1 2
unitwo.Request.setReady(boolean) 1 1 1
unitwo.Request.setTransfer(boolean) 1 1 1
unitwo.Request.whetherInElevator(int,Boolean) 2 1 3
unitwo.Request.whetherOutElevator(int) 2 1 2
unitwo.SafeOutPut.println(String) 1 1 1
unitwo.ViceController.ViceController(Controller) 1 1 1
unitwo.ViceController.addRequest(Request) 1 1 1
unitwo.ViceController.cleanSet() 1 5 5
unitwo.ViceController.comInElevator(int,boolean,String) 1 5 5
unitwo.ViceController.comeOutElevator(int,String) 1 5 5
unitwo.ViceController.getCustomer() 1 1 1
unitwo.ViceController.getMaxMinFloor(Boolean) 3 3 3
unitwo.ViceController.getNextFloor(int,Boolean) 4 4 4

​ 与上次作业有些类似,复杂度较高的方法是Controller为电梯分配Request的几个方法和在这几个方法中调用的判断该Request是否分配给该电梯的方法。这些方法都具有复杂的判断条件,导致最后复杂度较高、耦合度也较高,不利于扩展,可重用性、可移植性都较差。

代码行数分析

mine unitwo Controller Controller 13 1 0
mine unitwo Controller startWork 5 2 0
mine unitwo Controller addElevator 13 3 2
mine unitwo Controller needTransfer 7 3 1
mine unitwo Controller throughRequest 37 9 1
mine unitwo Controller getTransferFloor 37 9 1
mine unitwo Controller setTarget 12 4 1
mine unitwo Controller secondPutRequest 11 3 1
mine unitwo Controller putRequest 10 2 1
mine unitwo Controller getRequest 43 10 4
mine unitwo Controller awaitElevator 15 2 1
mine unitwo Controller signalElevator 14 3 0
mine unitwo Controller getRequsetChange 43 10 3
mine unitwo Controller getSize 3 1 0
mine unitwo Controller setStop 12 2 0
mine unitwo Elevator Elevator 14 1 6
mine unitwo Elevator addRequest 4 1 1
mine unitwo Elevator run 52 10 0
mine unitwo Elevator whetherAvailable 10 2 1
mine unitwo Elevator changeUpdown 3 1 0
mine unitwo Elevator toTargetFloor 33 5 0
mine unitwo Elevator arriveDestination 22 3 0
mine unitwo Elevator whetherInSetBegin 22 6 1
mine unitwo Elevator whetherGetRequest 11 3 1
mine unitwo Elevator whetherGetRequestChange 8 2 1
mine unitwo Elevator openDoor 7 2 1
mine unitwo Elevator closeDoor 7 2 1
mine unitwo Elevator arriveFloor 7 2 1
mine unitwo Elevator addSubFloor 8 2 0
mine unitwo Elevator changeDirection 7 1 0
mine unitwo Elevator changeElevatorDirection 26 4 0
mine unitwo Elevator setElevatorState 3 1 1
mine unitwo Elevator setTargetFloor 3 1 1
mine unitwo Elevator getElevatorState 3 1 0
mine unitwo Elevator isUpdown 3 1 0
mine unitwo InputRequest run 38 7 0
mine unitwo MainClass main 5 1 1
mine unitwo Request Request 15 2 5
mine unitwo Request setOutFloor 9 2 1
mine unitwo Request getFinalFloor 3 1 0
mine unitwo Request setFinalFloor 3 1 1
mine unitwo Request isReady 3 1 0
mine unitwo Request setReady 3 1 1
mine unitwo Request getId 3 1 0
mine unitwo Request setTransfer 3 1 1
mine unitwo Request isFirstTravel 3 1 0
mine unitwo Request isTransfer 3 1 0
mine unitwo Request getInFloor 3 1 0
mine unitwo Request getOutFloor 3 1 0
mine unitwo Request isUpdown 3 1 0
mine unitwo Request whetherOutElevator 8 2 1
mine unitwo Request whetherInElevator 8 2 2
mine unitwo Request outElevator 7 2 1
mine unitwo Request inElevator 7 2 1
mine unitwo SafeOutPut println 3 1 1
mine unitwo ViceController ViceController 6 1 1
mine unitwo ViceController addRequest 11 1 1
mine unitwo ViceController getNextFloor 26 4 2
mine unitwo ViceController cleanSet 17 5 0
mine unitwo ViceController getMaxMinFloor 17 3 1
mine unitwo ViceController comInElevator 14 4 3
mine unitwo ViceController comeOutElevator 13 4 2
mine unitwo ViceController getCustomer 9 1 0

​ 从代码行数、每个方法的规模上也可看出上述复杂度分析中遇到的问题。行数较多的类也是复杂度较高的类,集中在分配Request的几个方法和电梯本身上行下行调度的方法。

多线程的协同及同步控制

​ 在三次作业中采取了较简单的线程设计,仅有电梯线程和输入线程两种。第一次作业中采取生产者-消费者模式,以RequestList为共享对象,后两次作业中采取Work Thread模式,以Controller为共享对象。
​ 主要在三种地方需要加锁。第一个是共享对象ControllerputRequest()getRequest()等需要判断电梯状态再调用的方法和改变电梯状态方法的同步互斥,第二个是维护电梯内部存储Request的容器和需要通过该容器得到电梯下一个停靠楼层等信息的方法的读写互斥,采用了读写锁提高效率,第三个是关于电梯的await()signnal()方法的锁。
​ 因为后两种锁内没有其他引用,所以即使第一种锁会嵌套后两种,也不会有循环引用导致的死锁。但关于第一类锁,因为在Elevator线程中需要判断的地方较多,即check-then-act较多,而且往往checkElevator中,act调用Controller方法,所以有一些锁加在了调用Controller方法的Elevator代码的内部,而难以通过将Controller设计为线程安全类来实现线程安全,虽然能实现线程安全的目标,但代码的可移植性、可重用性较差,同时也增大了加锁的区域,降低了效率。

用SOLID原则进行分析

  1. SRP原则

    ​ 每个类或方法都只有一个明确的职责。

    ​ 作业中采取Work Thread模式。InputRequest类为委托者(Client),Controller类作为通道(Channel),Elevator类作为工人(Worker),Request类即为请求。Controller类作为共享对象,同时承担了调度的责任,为每个Elevator分配合适的Request,并且数量不超过上限,Elevator只负责完成分配给他的请求。每个Elevator都实例化的ViceController,管理分配给该电梯的乘客,进行电梯内部乘客进电梯和出电梯的调度。多数方法和类都拥有明确的职责。

  2. OCP原则

    ​ 无需修改已有实现(close),而是通过扩展来增加新功能(open)。

    ​ 三次作业中都采用Look算法,第一次使用生产者-消费者模式,后两次采取Work Thread模式。代码变动不多,仅在迭代的过程中增加了一些关于分配到哪个电梯以及换乘策略的调度,修改了一些关于电梯等待或是停止的判断条件。虽然针对这三次作业来说代码变动很少,但都需要修改已有代码,而且没有使用继承和接口,扩展性还是较差。

  3. LSP 原则

    ​ 任何父类出现的地方都可以使用子类来代替,并不会导致使用相应类的程序出现错误。

    ​ 在本次作业中无继承。

  4. ISP原则

    ​ 一个接口封装一组高度内聚的操作。

    ​ 在本次作业中未使用接口,使代码的灵活性和扩展性都较差,不符合这一原则。

  5. DIP原则

    ​ 依赖倒置原则。

    ​ 因为没有使用接口,所以这一原则的完成度也较差。

分析bug

  • 新建一个类,随机生成测试数据,将生成数据直接输入到程序中。通过改变生成输入时间的范围和楼层的范围进行不同的测试。检查结果是否有死锁、超时或者WA。
  • 调试时,新建一个Print类,在其它类中调用Print类的静态方法,输出关键信息,同时以断点调试和JProfiler辅助。
  • 在三次强测和互测中均未发现bug。
  • 在互测时主要通过测试判断是否有死锁、超时等来发现bug。

对比和心得体会

​ 在本单元作业中,我学习到了许多多线程方面的知识,如:线程安全、多线程设计模式等,学会了应用生产者-消费者模式和Work Thread模式,掌握了电梯调度的Look算法,然后在Look算法的基础上扩展,也取得了较好的性能分。但还存在一些问题:

  • 虽然在三次作业,代码的修改量不大,但没有使用继承和接口,使代码的扩展性较差。

  • 为了应对check-then-act,部分锁加在了代码内部,很难通过设计线程安全的共享对象类来解决一些线程安全问题。

  • 线程的run()方法不够简洁,承担了很多功能。

  • 主调度器Controller承担了较多功能。

  • 有许多复杂的判断语句,导致代码的复用性较低、复杂度较高。

  • 在部分时候为了结果的正确性和性能的提高,一定程度上牺牲了一些可读性。

  • 多线程程序中debug的难度较大,有时候因为设计上的疏漏,需要在debug上花费很长的时间。

​ 在本单元的学习中,我受益匪浅。多线程与单线程有很大的不同,虽然在这三周学习了许多关于多线程的设计和知识,但还有许多不了解的地方,希望能在以后更好的掌握多线程,设计出更好的架构。

发表评论

0/200
450 点赞
0 评论
收藏