• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

Recommended Posts

第二单元总结

一、同步设计

在这三个作业中,只有synchronized修饰符用于同步线程,主要保护读写冲突。在所有三个作业中,OutputQueue类用于封装输出信息,以确保其线程安全。对于使用最频繁的共享类RequestQueue,其读写方法getOneRequest、addRequest、removeRequest及其属性inputEnd和taskCounter都是用synchronized修饰符修饰的。因为RequestQueue的同步处理已经完成,所以各级调度器和升降机可以直接调用RequestQueue类对象的方法,不会造成线程安全问题。

二、调度设计

1.第五次作业调度设计

在这次操作中,每个座位只有一部电梯,调度类只为后续操作的扩展做准备。在这个操作中,请求只是直接分配给唯一的电梯,没有实质性的作用,自然也就根本没有调度策略。

电梯请求调度采用Look算法,即如果有同方向的捎带请求,就沿当前方向运行,否则就反向运行。本次运行中电梯的调度设计将在后续运行中继续使用。

2.第六次作业调度设计

这个作业开始使用两级调度,即主调度器是一级调度器,FloorScheduler和seat scheduler是二级调度器。

当输入类InputThread输入请求时,添加电梯的请求将被直接执行,添加运动的请求将被添加到与调度程序共享的RequestQueue类对象schQueue中。实际上,这是一个一对一的生产者-消费者模型,其中InputThread是生产者,Scheduler是消费者,schQueue是容器。

调度器取出schQueue中的请求,按照垂直移动和水平移动的类别分配给相应的座位调度器和楼层调度器,这表明请求队列被添加到座位/楼层调度器的请求列表中。

FloorScheduler和BuildingScheduler取出它们的requestQueue请求,并根据它们所管辖的电梯是否空闲、它们是否正在经过以及空闲空间的数量等信息将它们分配给每台电梯,这表明移动请求被添加到电梯的等待列表中。

3.第七次作业调度设计

这次作业是在第六次作业的基础上修改的。

每个移动请求都添加了当前位置、目标位置以及是否已到达arriveSwitchFloor的属性。当移动请求进入调度程序时,根据当前位置和最终目标位置设置当前目标位置,以便满足第六个作业移动请求的数据限制。当乘客移动到当前目标位置时,再次进入调度器管理的schQueue,结束移动或重复上述过程。由于此职务数据的限制,任何请求最多会以三个排班结束。

具体来说,设置当前目标位置的策略如下:

1)如果当前位置与最终目标位置仅相差楼层或楼层,则将当前目标位置设置为最终目标位置;

2)否则,判断arriveSwitchFloor是否为0;

3)如果为0,找到换乘楼层,将当前目标位置设置为当前楼层下的换乘楼层,并将arriveSwitchFloor设置为1;

4)如果为1,则将当前目标位置设置为最终目标位置的楼座下的当前楼层。

在上述策略的步骤3中,用于找到中转楼层的算法如下:

1)根据每栋建筑中所有电梯运行时间的调和平均值估算建筑性能(电梯越多,单台电梯运行时间越短,建筑性能越高);

2)在起始楼层和目标楼层之间寻找可达楼层,满足高性能建筑运行尽可能多楼层的要求;

3)如果没有找到可到达楼层,则找到运行楼层数最少的可到达楼层。在运行层数相同的情况下,满足高性能建筑运行尽可能多楼层的要求。因为一楼有水平电梯,可以到达任何座位,所以这一步不存在找不到无障碍楼层的情况。

当分段请求到达楼层/楼层调度员时,根据以下策略将其分配给其管辖下的电梯:

1)如果有空电梯,直接将请求分配给空电梯;

2)否则,如果有

3)否则,根据电梯剩余容量、候乘人数、运行速度等参数计算电梯的性能值,将请求分配给性能值最高的电梯。

特别是,taskCounter被添加到该作业中,作为结束流程的基础。当通用调度器分配分阶段移动请求时,taskCounter递增1;当电梯完成分阶段移动请求时,taskCounter递减1。当输入完成时,请求序列为空,任务计数器值为0,所有线程将停止运行,进程将结束。

三、架构模式

1.架构展示

由于第五个和第六个赋值是第七个赋值的子集,这里只显示第七个赋值的结构和三个赋值的迭代关系。

tersetter">第七次作业UML类图(省略构造方法、Getter、Setter):

5bensr3atxw3869.png

第五次作业架构:

仅有图中(Building)Scheduler、(Vertical)Elevator、RequestQueue、(Move)Request、InputThread、OutputQueue、OutputLine类,满足本次作业的基本要求。

第六次作业架构:

在第五次作业的基础上添加了Scheduler、FloorScheduler、HorizontalElevator类,满足横向运输需求,且二级调度架构基本形成,但总调度器Scheduler的调度逻辑非常简单,仅需根据运输类型(横向/纵向)将运输请求分配给楼层/楼座调度器即可。

第七次作业架构:

基本沿用第六次作业架构,仅对Scheduler调度逻辑进行修改,具体调度策略见上文“调度设计”部分。

2.协作关系

第七次作业UML协作图:

a2zen0jow2w3870.png

四、bug分析

1.自己的bug

第五次作业和第六次作业中都未发现bug。

但是在第七次作业中由于测试数据构造不足,出现了致命bug,导致强测得分极低:楼层调度器在给横向电梯分配请求时没有判断开门信息,从而导致横向电梯接收到无法运输的请求而在楼座中无限循环运行。

发现此问题后,解决办法比较简单,仅需在楼层调度器分配请求处加入判断语句即可。

2.别人的bug

主要结合自己遇到的bug和理论课学习中提到的可能出现的bug构造数据进行测试,同时构造逻辑较复杂的请求集合以及同一时间输入大量请求的数据以测试代码的逻辑正确性和线程安全性。

五、心得体会

1.线程安全

这一单元我仅利用了synchronized修饰词对涉及到读写冲突的方法上锁,且并未发现线程安全问题。

由于课程组对CPU使用时间的限制,我使用wait-notifyAll方式进行程序编写,避免了死锁和轮询的发生。

在第六次作业完成时,发现了程序无法结束的问题,即忙等问题。经过排查,发现由于过早对第七次作业进行预判且没有配套完整的迭代措施(如增加taskCounter作为程序结束标志之一),导致总调度器线程和电梯线程之间没有反馈路径,从而总调度器无法知道请求是否以及全部完成。经过删除一些多余代码段后,程序结束逻辑保持与第五次作业相同,问题得以解除。

本单元的不足之处在于,上锁的方式较为单一,显得比较笨重和呆板;而且没有使用其他锁的类型,导致对相关问题的理解不够深入,仅停留在了解决基本问题的层面。这样做虽然对于任务驱动的工程而言并无大碍,但对于个人的思维拓展和能力提升是不利的。

2.层次化设计

汲取了第一单元的经验,在完成本单元作业时,我有意为后续的迭代拓展预留了空间,有效避免了重构。

在第六次作业时,已经初步形成二级调度的架构,总调度器-楼层/楼座调度器-电梯的层次化设计让移动请求更有条理地被分配到合适的位置。每个层次只需各司其职,接收来自上一级的请求,并反馈本级的必要信息,既有利于维护线程安全和功能正确,也加强了代码的扩展性和可读性。

在第七次作业时,二级调度的层次化设计的优势更加突出,一个复杂的请求在经过一次从上到下的调度和运输后就会变简单,而被重新置于顶层再次调度。在经过有限次(不超过三次)层次化调度后,该请求会被简化为同楼座的运输,回归了第五次作业的基本功能。这种类似于递归下降的总调度策略也是一种层次化的设计,与线程的层次化设计相结合,让代码的维护与扩展更易展开。

Link to comment
Share on other sites