OO第二单元总结

同步块的设置和锁的选择

  初次接触多线程编程,第一次代码写得非常struggle... 我设置了两个存储乘客的容器:

  • RequestList,用于存放待调度的乘客,InputThread添加乘客,Scheduler从中取出交给Elavotor。

  • TaskList,用于存放待执行的任务,InputThread添加乘客,Elevator从中取出执行任务,同时TaskList还有一个getFromFloor方法,告诉电梯去哪里接人(离当前最远的地方,并且在路上捎带),一个getToFloor方法,告诉电梯目的楼层。

  一开始在需要同步的地方都采用嵌套的synchronized,频繁出现死锁问题。后来选择将这两个类的公共方法都设置成同步方法,其他类在调用的时候就不需要考虑线程安全问题,只需要在恰当的时候wait以及notifyall就可以了。

 

调度器设计

  • 第一次作业

    因为只有一部电梯,调度器只起到了简单的中转作用。InputThread读入的乘客信息存入RequestList中,调度器从中以先进先出的方式把任务给电梯。第一次设计的时候出现了不能结束、没人也会开门关门、超时、不在电梯里的人出去了、没有ctr d 就不会动等一系列问题。

  • 第二次作业

    多电梯,调度器按照电梯当前的任务分配,能捎带且没有满的优先捎带,如果没有能捎带的电梯,就分给当前任务数最少的电梯。

  • 第三次作业

    总的来说优先级是CBA,主要按照优先级划分,为了防止出现ABC都满而任务全都丢给最慢的A的情况,这里调度采用循环,即直到分配完毕才会跳出循环。此外,做了一些简单的换乘,比如拆分了奇到偶且楼层大于8的任务。

     

第三次作业架构设计的可扩展性

  • 画UML类图

    

  主类开启Scheduler,Elevator,InputThread线程,InputThread将乘客信息存放在RequestList中,每个Elevator有自己的TaskList类,同时这些TaskList存放在一个ArrayList容器中,由InputThread,Scheduler,Elevator三者共享(这里其实就造成高耦合,但是由于新增电梯会新增TaskList,没有想到更好的实现方式)。

  从功能设计上来说,每一个类都有自己的功能,比如Elvator不关心RequestList中的人,只是问TaskList要去哪里,然后每一层看一下要不要捎带、开关门,从这一角度说各部分的功能还比较专一。但我自己非常嫌弃数据结构的设计,为了实现这些功能,共享的范围比较大。

  从性能设计上来说,我考虑的是部分捎带,因为BC的速度大于A,对于从奇数楼层到偶数楼层的任务会进行一定的拆分(考虑到换乘的消耗,两个楼层之间大于8才会拆分),

  • 画UML协作图

      

    数据结构的设置并不合理,导致关系比较复杂,有点难以管理。从可拓展性上来说,因为采用了调度器的方式,后续新增要求应该会比较利于扩展。

分析自己程序的bug

  • 第一次作业在互测和公测没有bug

  • 第二次作业因为懒惰...没有进一步思考调度以及没有充分测试导致挂了两个点,而且对我来说是非常好改的bug....当事人至今非常后悔...

  • 第三次作业,写了多余的notifyall,策略的时候又有多余的循环,造成CTLE...本来其实只需要在第二次作业的基础上稍微改一下,当事人至今非常后悔..

心得体会

  第一次作业的时候第一次接触多线程,思考的过程比较struggle,但是在思考过程中除了学到了知识以外,发现了自己想问题的坏习惯:在框架没有定好之前就开始想细节的实现问题,然后细节实现如果出现了障碍,就会开始调整甚至改变框架,我觉得这样分析问题的方式效率是很低的,想到后来完全搞糊涂了又要从头开始理思路。

  此外,学习的设计模式并没有很好的被运用,比如之前助教有提到的策略模式,在这次作业中我对于不同时间段的策略选择其实非常简单,实际上只是在早上多开了一会门等人,对于夜晚没有做特殊处理,这部分的性能就很低。

  第二三次作业都做得很不理想,主要原因我认为是缺少测试以及对多线程的理解不够,导致写得稀烂…唔繼續加油!

posted @ 2021-04-25 14:15  nie-s  阅读(89)  评论(1编辑  收藏  举报