2024年春季学期北航OO第二单元总结博客

李昊琛 + 22371042 学生 2024-04-19 15:39:09

2024年春季学期北航OO第二单元总结博客

1. hw5

1.1 题目回顾

本次作业要求建立第二单元的底层框架,即多线程电梯。在本次作业中需要实现六个电梯的建立并要实现电梯调度,在本次作业中,乘客指定要乘坐某一电梯。

1.2 设计分析

img


在本次作业中,我设计了3个线程类、2个共享类和1个储存类。
其中三个共享类分别为输入线程InputThread、调度线程Schdeule、电梯线程Process,两个共享类为Main和RequesQueue,一个储存类为Request。运行过程中,Main开启全部的线程(包括一个输入进程、一个调度进程、六个电梯进程)并定义一些共享的变量。InputThread调用官方标准输入包获取输入并封装为Request类变量,通过RequestQueue共享类传递给Schedule,Schedule线程执行分类和分发指令,将分发完的指令通过RequestQueue类传递给指定的电梯进程,电梯运行接送乘客。

1.3 电梯运行策略分析

本次作业我没有采用指导书提供的算法,而是自己定义了一种算法。我的算法如下:
电梯根据有无人在等待电梯和有无人正在电梯里可分为四种情况,我对这四种情况分别处理。同时我将电梯的动作原子化成两类,第一类是电梯运行,第二类是电梯开门上下乘客关门,我定义在一个周期内只执行这两类动作中的一个,那么在函数中我只需要做两件事:第一件为判断有没有人上下电梯然后执行上下乘客指令,第二件判断移动方向执行移动指令。
1.在没人等电梯且没人乘坐电梯的情况下,可以直接将电梯挂起,执行wait或者sleep;
2.在没人等电梯在有人乘坐电梯的情况下,只需要判断有没有乘客要下电梯,如果有,就执2行乘客行为并结束周期,如果没有,就判断移动方向执行移动行为并结束周期;
3.在有人等电梯但没人乘坐电梯的情况下,只需判断有没有乘客要上电梯,如果有,就执行乘客行为并结束周期,如果没有,就判断移动方向并执行移动行为并结束周期;
4.在有人等电梯且有人乘坐的情况下,实际上是上面两种情况的综合,先判断有没有人要上下电梯,如果有就执行乘客行为并结束周期,否则就判断移动方向并执行移动行为并结束周期;
在情况2下,移动方向定义方式为距离电梯最近的等待者的方向。在情况3下,移动方向定义为距离电梯最近的乘客的目的地的方向。在情况4下,移动方向定义方式和3相同,但是考虑到性能因素,当电梯上一层或者下一层有人要上电梯时会去专门接这名乘客。

1.4 同步与锁

在本次作业中我采用的是给线程的方法上锁的方法,本次同步情况为一方只会写入,另一方只会获取一个指令并删除,所以给方法上锁即可。

2. hw6

2.1 题目回顾

本次作业乘客不指定使用哪一部电梯,需要自行判断。同时新增RESET方法,被reset的电梯需要将接受的请求全部归为未处理状态,然后就近停止更改自己的参数。

2.2 设计分析

img

本次作业整体架构与第一作业相比没有比较大的变化,只是指令分为了personRequest和resetRequest两种,我们只需要修改的一部分方法即可。

2.3 分配算法

本次我采用了最简单的分配算法,我进行伪随机分配,遍历六个电梯,当遍历到某个电梯时如果该电梯处于可接客状态就分配给这个电梯。
对于reset方法,我选择直接将被reset的请求分配给原电梯,这样就不会双向写共享类,不会出现问题。

2.4 同步与锁

本次的同步情况与hw5完全相同,不作赘述。

3. hw7

3.1 题目回顾

本次作业新增DBreset指令,将电梯重置为双轿厢电梯。

3.2 设计分析

img

本次新增了一类线程和一个共享类。新增的线程为双轿厢电梯,共享类为每两个双轿厢电梯的沟通方式。在无DCreset指令之前,所有行为与hw6相同,在有DCreset指令之后,process类将创建两个电梯作为双轿厢电梯并开启,同时process不再作为电梯运行,而是作为电梯井里两个电梯的局部调度器执行。

3.3 双轿厢电梯策略

我选择在每个电梯井的两个电梯之间设计一个共享类,在进入共享层时当某个电梯将要移动时就将自己的楼层传到共享类中,在离开共享层时完全离开后将自己的楼层传入共享类中,其他行为影响不大。当电梯要进入共享层时就访问共享类获取另一个电梯的位置信息。此外我对乘客的处理是永远只坐同一个电梯井里的电梯。

3.4 同步与锁

在本次中新出现了双轿厢电梯内部的信息交流,二者均是读写权限,这里就只能采用给对象上锁的方法了,否则会出现线程冲突问题。

4. bug分析

本次作业我出现的bug主要分为两种,一是线程退出问题,二是线程同步问题。
对于线程冲突问题,我的问题是电梯进程在该结束时未结束,处理方法为仔细检查退出的判断条件,要把线程退出的条件全部列出来,我就是漏了一种退出的条件,导致线程不该退出时直接退出。
对于线程同步问题,我的问题本质上不是同步有误,而是同步和输出之间逻辑有误。我的输出并不是和同步过程绑定的,所以会出现取消一个请求之后刚判断到对应的输出还没有被receive,但是已经输出了receive。我的处理是将二者写到一个语句块里进行绑定,这样就不会出问题了。
总的来说多线程debug还是比较困难的,我采用的方法是分析输入,然后找到出问题的情况,在那种情况下进行大量print来找到bug。

5. 心得体会

多线程程序设计时首先要特别注意线程间的同步问题。当处理到一个共享的属性或者类时要思考到读写权限加上合适的锁。此外对于线程的退出条件也一定要仔细判断,确保线程不会提前退出或者不能退出。
在层次化上,一定要梳理好哪个线程是什么作用,不同线程间的同步是通过哪个类实现的。理清了这些就不太会写乱。否则可能自己都看不懂自己写的代码

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

301

社区成员

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

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