BUAA_2024_OO Unit2 多线程电梯调度

刘思涵-22371386 2024-04-19 15:13:28

前言

本单元的第二次作业时,因为各种原因汇总,导致没有时间思考架构,程序结构混乱,线程不安全,本次作业的实现简直是灾难,不具有参考性

第五次作业——指定电梯多线程调度

实验思路

本次作业指定了六台电梯,并且所有的乘客请求都是直接下发至电梯处,不需要考虑电梯之间的竞争问题。因此本次电梯只需要保证多线程之间的互相独立,同时保护好临界资源的安全访问即可。

关于电梯线程的设计,我将电梯分为三个部分,首先是电梯线程本身,作为继承了Thread类的电梯类,在每一个电梯对象中独自运行run方法,接收外部信号并进行开关门和移动的基本操作。其次是候乘表类,用于记录当前电梯已接收的请求,在特定层提醒电梯开关门上下乘客,并且可以计算超载。最后是策略类,用于根据候乘表的内容,向电梯发出信号,指挥电梯运行。

在电梯之外,还有服务器类,用于将公共的请求分发到特定电梯处,因为在第一次时会指定电梯,因此这里目前不需要设计分配算法。输入线程类,用于将输入的请求转换为电梯可以接受的任务。任务类,用于电梯保存,其下有乘客任务,移动任务,休眠任务等等子类,分别标记着电梯的运动目标。最后是输出类,将电梯的数据按照格式进行输出。

第六次作业——不定电梯调度与重置

第六次作业中添加了多个电梯竞争取得请求的部分,因此要完善服务器类中的分发部分。除此之外还添加了重置请求,电梯可能会中途停止,导致请求的流动方向从单方面流动变为双方向流动,因此关于线程关闭和分发优先级问题需要重新考虑

在本次作业中,因为时间问题,没有完善的思考流程,因此实现过于混乱,代码bug层出不穷,不具有参考价值

关于分发策略,因为没有时间再重新写一个分发策略,因此先试用轮盘分发,实测效果并不好

重置问题,首先要保证重置时不能运动超过两层,因此要把重置的优先级拉高,即使在运行途中也要进行重置。这样导致乘客可能没有达到目的地就被放下,要考虑将请求重新打会服务器,再进行分发。

这里两个服务器的优先级是不同的,在第一个服务器关闭后,第二个服务器再考虑关闭

 

第七次作业——双轿厢电梯调度

双轿厢电梯的添加增加了如下的潜在问题:

  1. 如何在电梯运行中途额外新增新的电梯线程

  2. 如何防止电梯碰撞

  3. 如何将一个请求分成多个部分,分别使不同的电梯承载一部分

  4. 双轿厢电梯的分配优先级如何保证

首先是新增线程的问题,我选择使用工厂模式,在电梯触发双轿厢电梯的重置后,调用工厂,在总的线程池中添加新的电梯

关于电梯碰撞问题,我设置了一个互斥访问的锁,用于锁住交接层,防止同时两个电梯在同一层。同时设置了驱离策略,使得电梯在试图进入交接层,但是发现已经被占用的情况下,会试图给另一个电梯发送一个离开当前层的请求,当另一个电梯空闲时,会直接远离,如果不空闲,则也会在接受任务后远离。

关于请求部分,我设置只要运行范围与请求范围有交集,并且能够接取,那就优先接取,到达交接层时强迫下电梯,并产生一个新的请求。

关于分配优先级问题,我默认即使中途下车的请求,也以全部是双轿厢电梯搭载的假设情形来计算消耗,并使用影子电梯策略进行服务器分配

但因为第六次作业遗留的大量问题,导致本次作业中,一旦作修改,都会出现大量bug,最后程序完成度低。

 除此之外,还设置了分发类,用以避免线程不安全的问题

 在分配策略部分,因为要参考当前电梯状态,导致出现了许多线程安全问题

线程安全问题

在三次作业中,线程安全的问题逐渐递进

首先是第一次作业,因为结构简单,临界资源只有Board类中的队列,因此为了防止出现线程安全问题,我选择将判断方法传入Board类的takeAll方法,在方法中会遍历所有对象,并根据判断方法的返回值决定是否获取该对象。

到了第二次,因为会出现双向的传递,线程安全问题更加复杂。我选择将Board分为高低优先级两种,分别按照第一次的规律设计线程安全。并且因为退回的请求不会再回到优先级更高的队列处,因此可以保证线程安全和正常退出

第三次作业,因为分发服务器要访问电梯进行分数裁定,而电梯又需要访问服务器回传请求,因此出现了多种不同的死锁问题,为了解决该问题,我设置了分发类,用于串联两方,两方访问对方都需要访问分发类,进一步保证线程安全问题

Bug问题

在本单元中,因为第六次作业的混乱,导致后两次bug层出不穷,目前仍没有完全解决。但是在解决线程问题时,因为会导致线程时间片的略微扰动,导致无法复现bug,但是仍有解决方法。首先是IDEA自带的内存快照工具,当程序出现死锁和无法结束时,可以通过IDEA的快照查找对应哪一个线程始终无法继续运行。至于其他运行错误问题,可以打印所有可能用到的数据,之后在不同环境下运行程序,尝试复现bug,并且根据打印出的日志进行debug

心得体会

本次作业是我彻底感受到迭代式开发体会的一次,因为第六次作业的紊乱结构,潜在问题,导致第六,第七次作业强测表现都很差。而剩余的大量bug也是牵一发而动全身,至今没有完全解决第七次作业的全部bug。从这一次作业,我深刻体会到线程安全和线程死锁问题的设计因素,之后再设计多线程程序时一定要提前分析好每一个潜在线程问题的具体类或者方法,建立尽可能简单的运行机制,保证程序不要出现过于复杂的调用关系。当调用复杂时,如果不使用synchronized修饰,则大概率会出现临界资源不安全的问题,而加入太多的修饰,又可能相互调用导致线程死锁

...全文
66 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

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

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