• BUAA-OO-第二单元总结


    BUAA-OO-第二单元总结

      OO第二单元马上要结束了,我们也亲身经历了传说中恐怖的电梯调度。总体来看三次作业主要有2个难点,一个是关于多线程的维护、线程安全的问题,另一个是调度策略的优化问题。多线程和单线程有很大的不同,由于第一次接触多线程,在线程安全,轮询等问题上处理的还不是很好,就难免会出现一些问题。当解决了线程安全问题后,三次作业就可以相对简单的写出来了,但随之而来的就是另一个问题,调度策略的优化。无论采用哪种调度策略,都会出现一些奇怪的数据,导致你的电梯可能比傻瓜调度还要慢,所以在性能和架构的权衡方面也是一个难题。

    第一次作业

      第一次作业是单部电梯的傻瓜调度策略,也就是每次只能接送一个人的VIP电梯。第一次作业我由于对多线程的不理解,在main中每读入一个请求,就new一个电梯线程并启动。所有电梯共享一个乘客队列。当输入null时,给电梯一个stop信号,当电梯送完最后一个乘客并且有stop信号,停止电梯线程。

      下图为本次作业的度量分析及结构图和时序图

      

      

      

      这次作业我的设计策略可以说十分差劲,仅仅用了单线程解决问题,并没有十分了解多线程的使用方法。这次作业的调度策略比较简单,所以并没有被找到bug,同理我也没有找到其他人的bug,但是通过看其他同学的代码学会了一些关于多线程的维护方法。

    第二次作业

      第二次作业是单部电梯的ALS调度策略,也就是允许电梯在运行过程中进行捎带。这次作业我用了两个线程,一个输入线程,负责读入请求并把请求加入到乘客队列中;另一个是电梯线程,负责运送乘客。在电梯每运行一层楼时,都要去遍历乘客队列是否有可以捎带的乘客。此外,电梯内部自带一个目标楼层队列,每进入一位乘客,将它的目标楼层加入到队列中,每次取出第一个目标楼层让电梯运行,如果再运行过程中有可以下电梯的乘客,同样将他们放下。电梯的停止条件与第一次的停止条件相同。

      下图为本次作业的度量分析及结构图

      

      

      

      这次作业应该说是我对于多线程程序的第一次尝试,总体来说还是学会了很多东西,对于多线程的维护,程序锁都有了一定了解。但由于调度策略的问题导致性能分几乎为0,因为这次的作业比较赶,并没有采用一个很好的调度策略,只是简单实现了ALS。此外,在强测和互测中被hack了4个测试点,都是因为考虑不周使得程序进入死循环,没有考虑到。hack了别人5次,发现很多人在处理某层楼既要上电梯,又要下电梯的情况时处理不当,以至输出出现问题。

    第三次作业

      第三次作业是电梯作业的终极版,共三部电梯,每个电梯可到达的楼层各不相同,也没有规定调度策略。这次作业我用了5个线程,一个输入线程,一个调度器线程,三个电梯线程。输入线程负责将请求加入总队列中,调度器负责取出总队列中的请求并根据一定策略分配给电梯,电梯我沿用了第二次作业的电梯,也就是ALS策略。关于请求的分配问题,我是进行了判断,如果能一部电梯送到则一部电梯送,如果不能,则将请求拆分为两部分一部电梯可以执行的请求,并把后一段请求进行标记(乘客id),当前一段请求执行完成后,把标记去掉,后一段请求便可以执行。

      

      

      

      

      

      这次作业相比前两次而言难度提升了许多,三个电梯线程实际上是一个类,其中涉及到一些锁,wait,notify等很多问题,一不小心考虑少可能就会出现死锁或者异常。这次作业的性能分同样几乎没有,其实本可以写一个基于ALS的比较好的调度策略,但由于时间不够,并且考虑情况比较多,结果没有写出来。此外,因为这次电梯有乘客限制,所以在每到达一层时进行先下后上是比较好的,但由于一开始没考虑到这个问题,所以由于这个也丢了比较多的性能分。幸运地在强测和互测中没有被hack,同时也没有hack到别人,感觉经过了2次作业之后大家多于多线程都维护的比较好。

    总结

       这三次作业我都是使用wait和notifyall解决问题的,除了电梯运行开关门之外,没有用过sleep。这样的设计策略使得CPU运行时间比较少,但必须要控制好各个锁之间的控制关系,否则一不小心可能就会出现死锁和轮询。(第二次作业就因为少考虑了一个if情况而导致轮询) 如果自顶向下看,基本都是上层线程notify下层线程,下层线程想停止,必须上层线程先停止,否则只能wait。我是采取这样的策略的,感觉还是比较好控制各个线程的。对于这几次的bug,其实是比较难发现的。因为多线程具有一定的不确定性,所以可能需要尝试许多次才能发现bug。同样我也是采取这样的方法,在测试自己和别人的程序时,对于一组测试样例要进行多次重复测试,当每次结果基本一致时,才可以认定为正确。第二次和第三次作业我认为我的设计策略还是不错的,逻辑、分类都比较清晰,也没有出现什么重大的线程安全问题。但是性能方面我设计的很差劲,由于自己时间和能力的不足,并没有设计出很好的调度策略。

      这三次作业我最大的收获就是学会了一些设计模式以及解决了多线程的相关问题,今后如果还会有多线程问题,我至少在多线程的线程安全方面不会有太大的问题,就可以花更多的时间投入到优化中。也希望自己在今后的作业可以取得更高的性能分。  

  • 相关阅读:
    返回一个整数数组中最大子数组的和(数组头尾连接)
    场景调研(补)
    《浪潮之巅》读书笔记3
    《软件工程》课程改进意见
    【每日scrum】第一次冲刺day6
    【每日scrum】第一次冲刺day5
    【每日scrum】第一次冲刺day4
    【每日scrum】第一次冲刺day3
    【每日scrum】第一次冲刺day2
    【每日scrum】第一次冲刺day1
  • 原文地址:https://www.cnblogs.com/monokuma/p/10757637.html
Copyright © 2020-2023  润新知