OO-Elevator-进化笔记


 

♦Elevator 1.0

 

整体框架:

  主要线程有两个:Demands线程(名字取得不太好)和Elevator线程,第一次作业没有加入调度器线程。Demands线程负责往托盘里面放入请求,Elevator线程负责把请求“消费完”,一个简单的生产者-消费者模式。托盘则是一个元素为Person的数组,这个数组就是这俩个线程之间的共享数据,线程间通过这个队列进行交互。

  线程加锁:在对Persons队列进行操作时会将整个操作锁住,以防止出现多个线程对同一数据同时操作时的安全性问题。例如Demands进行add操作时加锁,Elevator进行remove操作时进行加锁。

  调度策略:采用的先来先服务(FCFS)原则,即在队列的头部拉取一个Person进行运行,运行过程中可以实现简单的捎带。

  类关系图:

    

  类复杂度分析:

    

 

 

     Elevator线程类的复杂度稍微有点偏高,电梯太臃肿了,这就是没有调度器的缺点。

 

  

 


 

♦Elevator 2.0

  

整体框架:

  主要线程有三个:Input线程、Control线程和Elevator线程,这一次作业加入调度器线程。Input线程相当于上一次的Demands线程,负责往托盘里面放入请求,Control线程负责把托盘里的所有的Person分配给电梯队列中的一个电梯。托盘依然是一个元素为Person的数组,这个数组是Input线程之和Control线程之间的共享数据,线程间通过这个队列进行交互。Elevator线程则自带一个请求队列,Control只是负责把一个个的Person们委托给某一个电梯,电梯则负责把Control交给自己的任务完成(自己具备了简单的捎带)。所以就相当于两个生产者-消费者模式。Input生产的Person给Control消费。Control得到了Person经过简单的处理分配给Elevator消费。

 

  线程加锁:主要的共享数据依旧是Persons队列,加锁也还是对队列操作时(增加元素、删除元素)进行数据的保护

 

  类关系图:(Main线程莫名其妙的独立出去了,明明有一个创建子线程的关系)

    

  类复杂度分析:

    

 

 

     相比于上次,这次复杂度稍微平均了点,Elevator和Input类复杂度都差不多,虽说Control稍微的超了点,但也算三个主要的线程工作分配得当。

 

 

 


 

♦Elevator 3.0

  

整体框架:

    主要线程(和第二次作业基本一样):Input线程、Control线程和Elevator线程,线程之间的交互也都差不多,除了换乘的实现(下面会提)

    换乘实现:在Person类中添加了firstTo和finalTo属性(目前仅仅支持换乘一次),当Input接收到人的请求时,会往Person类中添加出发楼层和目的楼  层,然后Person会自己进行判  断,看是否需要换乘(由人自己决定,内部会判断时间长短),如果需要换乘,则会出现一个firstTo作为过渡楼层,也  可以没有换乘。当人到达自己的目的楼层时(目的楼层可以是firstTo,也可以是finalTo),会进行判断,如果到达的是最终的目的楼层,则就finish了一个  Person,如果没有到达,只是到达了过渡楼层,电梯就会抛出去一个新的Person,内部队列可以删除,抛出去的新Person也会最终进入另一个电梯完成电  梯之旅。

  类关系图:

    

  类复杂度分析:

    

 

 

 

 

 

 


 

 

总结

  bug分析:

    ♣第二次作业出现了无限等待的情况,Elevator没有及时的关闭,而是一直的wait,后面发现后,将Control的结束信号传给了Elevator,达到关闭线程的效果。

    大致的结束过程:Input结束-->传递信号给Control-->Control里的队列为空且Input结束-->传递信号给Elevator们-->Elevator内部为空且Control结束-->finish!

    ♣第三次作业同样是在线程关闭时出现了问题,与第二次作业不同,第三次作业由于换乘的缘故,电梯也可以成为请求的生产者,所以Input结束且Control为空并不能让Control结束,Elevator可能还会抛出请求,所以Control结束条件加上了一个Elevator全部处理完毕的信号,最后达到了效果。

  多线程小结:

    多线程的重难点主要是共享数据的安全性问题,多个线程不能同时更改数据,应该加锁保证只有一个线程进入临界区。而临界区的大小也非常关键,  太大可能会使性能大大降低,太小则可能无法保证数据的安全,所以我们就要重点分析好锁加的范围,不必要的时候i可以不加(例如读操作可以允许多进  程同时读),写操作就必须保证只有一个在对数据进行更改。第二、三次作业性能分都在85-90分左右,主要是调度的调度策略太过简单,不过相比上一  单元的惨不忍睹以及好太多了,重构次数也不多,只是第一次和第二次之间有了较大的更改,之前过完第一个单元只有一次有效作业,还以为要提前进入  补给站了,还好第二单元给了我信心,接下来两个单元继续保持,冲冲冲!

 


 

 
 
 
posted @ 2021-04-27 18:36  Sinsoledadℳ  阅读(51)  评论(0编辑  收藏  举报