301
社区成员
发帖
与我相关
我的任务
分享完成乘客请求,即对于每个乘客请求(起点层,终点层),需要调度电梯将其完成,并将必要的运行信息通过输出接口进行输出。具体而言,你需要控制电梯上下行,开关门的动作以及控制乘客进出电梯来将乘客从起点层运送到终点层。我们的电梯系统有多部电梯,你需要合理的调度这些电梯来达到更好的性能(第一次作业指定了接送乘客的电梯)。


本次作业强制乘客登上指定电梯,无需设计调度策略,只需按照电梯号分配乘客。
根据往届学长的博客,我选择了LOOK策略
LOOK策略:
- 电梯初始化设置楼层和方向
- 到达某楼层,首先判断电梯内人是否可出,若可,放出。
- 判断本层是否有请求者目标楼层在当前电梯运行方向上且电梯未满载,若有,则捎带。
- 若电梯内有人,则继续按照原方向移动
- 若电梯内无人,但等待队列有人,且出发楼层与电梯方向相同,则电梯原方向移动
- 若电梯无人,但等待队列有人,且出发楼层与电梯方向不同,则电梯转向
- 若电梯无人,且等待队列空但未结束,则原地等待请求输入
- 若电梯无人,且等待队列空且结束,则结束电梯线程
本次作业涉及多线程共享访问的对象只有一个:总等待队列(waitQueue),所以将涉及waitQueue的加,删,读取方法加上synchronized语句块即可。
e.g.
public synchronized void addRequest(PersonRequest personRequest) {
personRequests.add(personRequest);
notifyAll();
}


由于本次作业我花了大量时间和精力处理reset指令的正确性,所以只采用了性能一般的均分算法。思想是:按照顺序将收到的请求平均分给6部电梯。出现问题:当电梯正在重置时如何分配,receive语句如何输出?
解决思路:在每个电梯内部新建一个队列(我称之为缓冲队列),存储电梯reset时接收的请求。在分配时若电梯在重置,则将请求放入电梯的缓冲队列,等电梯重置结束时输出receive语句。
电梯仍采用LOOK策略
本次代码需要被多线程共享的对象有:总等待队列,电梯的reset信号(被Schedule线程读取和写入,被ElevatorThread线程读取)
public synchronized void dosth1(){
dosth2();
}
public synchronized void dosth2(){
dosth1();
}
经过努力排查,最终我把所有的嵌套锁全都改成了单层锁,过了。教训:不要随意写锁保证不必要的线程安全,既影响性能,也可能会造成死锁难题。新增DoubleReset指令,将单轿厢变成双轿厢电梯


由于新增reset指令,电梯的状态变成了三个:正常态,normalReset态,doubleReset态。所以我把AtomicBoolean改成了AtomicInteger,分别用0,1,2表示。调度策略仍然是均分策略。
新增一个类OccupiedFlag,描述换乘层是否被占用。具体细节如下,实现方法参考了讨论区姜涵章同学的分享。注意,这个类实际上起到A和B中的桥梁作用,让二者都可以访问换成层的占有信息。
public synchronized void setRelease(int eleId) {
this.state = State.UNOCCUPIED;
//TimableOutput.println("finish wait " + eleId);
notifyAll();
}
private synchronized void waitRelease(int eleId) {
notifyAll();
while (state == State.OCCUPIED) {
try {
//TimableOutput.println("get to wait " + eleId);
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public synchronized void setOccupied(int eleId) {
waitRelease(eleId);
state = State.OCCUPIED;
notifyAll();
}
这次作业的锁的设计和hw6没有特别大的差别,被多线程共享的对象:总等待队列,电梯的reset情况。我的调整是将AtomicBoolean改成了AtomicInteger,表示新增的doubleReset状态。
注意A或B双轿厢等待另一电梯离开换乘层时,被唤醒的条件,应该是电梯处于下行(A,若B则是上行),且到达换乘楼层下(或上)的一层。若仅仅是到达换乘楼层上(或下)的层,会出现等待已经被路过换乘楼层前一层的电梯A或B唤醒,导致相撞。