301
社区成员
发帖
与我相关
我的任务
分享目录
这次作业的线程包括调度线程、输入线程、任务线程(电梯)。三个线程均为生产者也均为消费者。其中waitqueue为总等待队列,为所有线程共有;每个电梯拥有一个processqueue,为自身任务线程和调度线程共有;此外还有noti类实例作为共享对象,只用于唤醒线程。主要功能共享对象(等待队列)均为requestqueue类。
上锁的办法主要由三种:锁对象、锁方法、Lock类
本次作业中主要使用锁方法,并有少量的锁对象。
requestqueue类中包括大量的锁方法,主要是功能部分;在电梯线程内含有部分的锁对象,主要用于wait方法和之后的唤醒。
调度器包括waitqueue和processqueues,功能为从输入线程中得到request放入waitqueue,从waitqueue中分配到procequeues中电梯的processqueue。调度器中存有各个电梯实例,用于得到状态,进行分配。
策略基于电梯的LOOK策略,结合LOOK策略的扫描特性,同向可稍带优先指数设为1,反向设为2,同向不可捎带设为3,与LOOK接收顺序一致,reset中的电梯设为4,等待队列超过20人的设为5,优先分配优先指数低的电梯,若最小指数大于3则等待。




hw5
本单元第一次作业中由于指定了接收乘客的电梯,故只需要考虑电梯运行的策略。
这次作业中我使用了教程中提到的ALS方法,即电梯的运行方向由当前的主请求决定,并在路上捎带同向请求
在我的设计中,每个电梯有单独的线程,数据的投喂与调度器同为main线程。数据投喂进调度器的全局等待队列中,再由调度器塞给每个电梯的等待队列,在电梯运行到合适的位置并开门后,会处理等待队列中可以上电梯的请求,将其变为电梯内乘客集合中的一份子。
每个电梯的行为决策都由各自的policy类负责给出,每个电梯线程都始终运行在 获得并更新主请求-执行动作 的循环之中,直到接受到来自外界main线程的终止信号。电梯在开门后处理本层的进出请求,将所有到达层为本层的乘客放出,并将等待队列中所有出发层在本层且同向的乘客放入,前提是电梯未满。
hw6
在本单元第二次作业中,由于允许自由分配请求,以及增加了电梯的重置,需要在调度器和电梯的运行策略上进行更多的考虑。
由于上次作业的ALS算法的性能分实在太低,这次采用look算法,即电梯不再由主请求引导,每次处理完当前全部的同向请求后再调头。同时基于LOOK策略进行分配。
对于电梯重置,电梯需要先将所有乘客放出,所有接受到的请求取消,然后静默1.2s完成重置,因此,电梯在接收到重置请求后的下个动作,即是开门并放出所有乘客。然而,电梯释放的不仅有电梯内乘客请求,还有注册队列和等待队列中所有的请求,这些请求都需要将起始层设为本层后交还给调度器,进行再次分配。
hw7
本单元第三次作业需要在hw6的基础上考虑双轿厢的重置和调度问题。
我设置18个电梯线程,1-6为初始电梯,7-12为双轿厢电梯下层电梯(A电梯),13-18为上层电梯(B电梯),接受到双轿厢重置时,初始电梯标志位关闭,双轿厢开启。电梯包含父子关系和兄弟关系。父子关系用于启动和关闭电梯,兄弟关系用于防止双轿厢相撞,同时锁对象锁住兄弟电梯的楼层。加入static类用于电梯中所有不用改变属性的操作。
稳定和易变部分
稳定:输入线程,调度线程,电梯线程的方法
易变:电梯线程的属性
主要是轮询和线程不能正常结束。轮询用wait和notify解决;线程结束条件如下:input中无输入;schedule中初始电梯中无reset,双轿厢中所有电梯都能解决自己的request,且input结束;elevator队列无人且schedule结束。
主要有两种方法:
一、idea中的调试切换线程
二、在代码中加入print,利用官方测试包
本单元最为折磨的地方在于写出线程安全的程序。同时,多线程的调试和bug复现也比单线程程序困难,因此更应该熟练掌握各种工具,借助工具来进行调试。