zoukankan      html  css  js  c++  java
  • OO第二单元总结——多线程电梯

    设计策略分析

    电梯1:

    任务:单部多线程傻瓜调度(FAFS)电梯

    实现:3个线程,单例模式

    Thread1:主线程

    Thread2:输入处理线程

    Thread3:电梯运行模拟线程

    构建一个共享对象,用于put、get请求,该对象全局唯一,被Thread2和Thread3共同拥有,给该对象的方法加同步锁synchronized,以确保请求队列的安全。

    通过wait、notify,使电梯和输入处理线程交替进入共享对象的临界区执行。

    电梯模拟行为:从队列取一个请求,获取其fromFloor、toFloor、personId,一次只进入一个请求、将该请求完成后再进入临界区获取新的请求,当取得请求为null时,表示没有请求了,结束电梯线程。

    电梯2:

    任务:单部多线程可捎带调度(ALS)电梯

    实现:总体架构与第一次没有太大变化,只是改了调度器的调度方法和电梯相应的请求处理行为

    调度器主要method:

    mainGet():返回请求队列第一个元素,传给电梯,作为其主请求;

    passGet():传入电梯的当前楼层和其主请求,返回可捎带请求队列;

    nobody_passGet():传入电梯当前楼层和其主请求的fromFloor,返回电梯接主请求的途中可捎带请求(相当于一个小优化);

    电梯requestHandler():电梯为空时,与调度器交互获得主请求,然后从当前楼层出发前往主请求的fromFloor,途中在每一层调用nobody_passGet(),在主请求进入电梯后,执行主请求,在每一层调用passGet(),并且在每一层进行判断,调整主请求为电梯乘客队列中的passger.get(0)。

    电梯3:

    任务:多部多线程智能(SS)调度电梯

    实现:电梯架构依然没有太大变化,仍然是单例模式。

    对于每个电梯,采取ALS策略。

    给PersonRequest添加一个bool变量canIn,true代表活跃(可进入电梯),flase代表休眠(暂时不可进入电梯),其作用为:由于特殊请求会换乘,因此调度器会将这类请求进行拆分成两条请求,前请求进入电梯,并将后请求的canIn设为false并留在请求队列,在前请求到达换乘楼层并出电梯后,激活后请求(即将后请求的canIn设为true)。


    OO度量

    电梯1:

    UML

    Complexity metrics

    电梯2:

    UML

    Complexity metrics

    电梯3:

    UML

    Complexity metrics

    度量分析:

    前两次作业的复杂度都较低,第三次作业中调度器类的总循环复杂度和平均循环复杂度都较高,用于拆分请求的方法复杂度也很高,主要原因是该method中用了大量的多重嵌套的条件控制语句和循环。

    设计原则分析:

    由于没有使用接口,只继承了thread类,此处不谈LSP和ISP;

    基本上三次作业基本符合SRP原则,每个类或方法都有一个大致明确的职责,但其实还能进一步明确各方法的职责;

    在第一次电梯的基础上,只需扩展调度器的调度方法,即可实现ALS调度,可见符合OCP原则;

    在第三次作业中,电梯类和调度器类的交互是依赖于抽象类实现的,并没有依赖于电梯类的具体对象进行交互,因而满足DIP原则。


    分析自己程序bug

    前两次作业没有bug,但是第三次作业在强测中几乎爆零,这个bug是由于思维定式,每部电梯在每层楼都和调度器进行了交互,因而导致电梯在不能停靠的楼层进行了开关门动作,增加一条判断语句即可修复该bug。


    分析他人程序bug

    很显然,本单元由于涉及到了多线程,又由于输入的定时投放问题,传统的hack策略已经不奏效了,所以我使用评测脚本来实现定时投放,并对其结果进行自动化测试。

    第一单元的作业,测试数据很容易构造,输出只有一个表达式,对于不太长的数据,基本可以通过肉眼判断其正确性,但电梯作业的输出是十分长的,尤其是第三次作业各电梯的输出相互交叉,难度更大。另外,电梯作业的bug可能很难复现,有时候评测机也会误判。


    心得体会

    本单元设计到了多线程,而多线程很重要的一点就是其线程安全,也是多线程的难点之一,通过对共享对象的方法加同步锁来实现临界区互斥,利用wait()、notifyAll()来调节线程进进入临界区的顺序,当然还有更多的互斥机制,可以弥补synchronized的一些缺点,例如高并发下会损失效率。这三次作业我都采用了单例模式,这使得我的三次作业架构基本相同。在设计层面上,尽量符合SOLID原则,可增强代码的拓展性、复用性。这三次作业,不仅使我接触了多线程,也让我对OO设计层面有了更深的理解。


    最后就是,针对我第三次电梯作业大翻车的情况,告诫自己,千万不要面向数据编程!!!

  • 相关阅读:
    47数据结构与算法分析之---查找的基本概念
    46数据结构与算法分析之---排序方法比较
    45数据结构与算法分析之---基数排序
    44数据结构与算法分析之---归并排序
    43数据结构与算法分析之---选择排序
    42数据结构与算法分析之---交换排序
    41数据结构与算法分析之---插入排序
    54数据结构与算法分析之---哈希查找
    40数据结构与算法分析之---排序的基本概念
    37数据结构与算法分析之---关键路径
  • 原文地址:https://www.cnblogs.com/wanzf-bky/p/10762098.html
Copyright © 2011-2022 走看看