总结性博客作业
第一次作业
(1)从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略。
第一次作业为单电梯傻瓜调度,可以采用生产者——消费者模型,是一个有一个生产者(标准输入电梯请求),一个消费者(电梯),中间的托盘共享数据为请求队列的模型。由于电梯没有容量限制,因此生产者生产的请求可以实时加入到请求队列中。消费者(电梯)每次从请求队列中取出一个请求并执行。只需要保证对请求队列的操作互斥就可以了。由于elevator的结束条件是input结束并且请求队列为空,所以elevator需要感知input是否结束,对此采取将input线程作为elevator的一个数据成员,这样就可以使用input.isAlive()来判断input线程是否结束。
(2)基于度量来分析自己的程序结构度量类的属性个数、方法个数、每个方法规模、每个方法的控制分支数目、类总代码规模计算经典的OO度量画出自己作业的类图,并自我点评优点和缺点,要结合类图做分析通过UML的协作图(sequence diagram)来展示线程之间的协作关系(别忘记主线程)从设计原则检查角度,检查自己的设计,并按照SOLID列出所存在的问题
(3)分析自己程序的bug分析未通过的公测用例和被互测发现的bug:特征、问题所在的类和方法特别注意分析哪些问题与线程安全相关关联分析bug位置与设计结构之间的相关性
第一次没有踩到bug。
(4)分析自己发现别人程序bug所采用的策略列出自己所采取的测试策略及有效性,并特别指出是否结合被测程序的代码设计结构来设计测试用例分析自己采用了什么策略来发现线程安全相关的问题分析本单元的测试策略与第一单元测试策略的差异之处
第一次也没有检查到别人的bug
(5)心得体会从线程安全和设计原则两个方面来梳理自己在本单元三次作业中获得的心得体会
只需要对共享数据的操作进行互斥就可以了。
第二次作业
(1)从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略。
第二次作业为单电梯ALS调度,仍旧可以采用生产者——消费者模型。
与第一次作业的区别在于:
- 电梯到了某一层楼后,需要检索请求队列中所有请求,取出其中能够被电梯捎带的请求,并放入电梯的loader队列里面。
- 第二次作业对CPU时间进行了限制,所以再采取轮询的方式获取请求是不行的。必须使用wait,notify方法。在请求队列为空并且没有输入的时候,让电梯线程wait,当再次有输入的时候让输入线程去唤醒电梯线程,这样做有效减少了CPU时间。
- input与elevator是两个平等的对象,将input作为elevator的数据成员是不合理的,因此设置一个共享变量hasInput,初值设置为true,当hasInput为true的时候,电梯线程就不会结束。只有当Input线程结束,由Input线程将hasInput设置为false,并且当请求队列为空的时候,电梯线程才能结束。
(2)基于度量来分析自己的程序结构度量类的属性个数、方法个数、每个方法规模、每个方法的控制分支数目、类总代码规模计算经典的OO度量画出自己作业的类图,并自我点评优点和缺点,要结合类图做分析通过UML的协作图(sequence diagram)来展示线程之间的协作关系(别忘记主线程)从设计原则检查角度,检查自己的设计,并按照SOLID列出所存在的问题
(3)分析自己程序的bug分析未通过的公测用例和被互测发现的bug:特征、问题所在的类和方法特别注意分析哪些问题与线程安全相关关联分析bug位置与设计结构之间的相关性。
自己的bug在于elevator的run方法少写了一行listout,导致有些人没有出电梯。
(4)分析自己发现别人程序bug所采用的策略列出自己所采取的测试策略及有效性,并特别指出是否结合被测程序的代码设计结构来设计测试用例分析自己采用了什么策略来发现线程安全相关的问题分析本单元的测试策略与第一单元测试策略的差异之处
测试策略是自己编写边界数据。
(5)心得体会从线程安全和设计原则两个方面来梳理自己在本单元三次作业中获得的心得体会
从第二次作业中,我踩到一个巨坑。那就是不能notify没有获得锁的线程,一旦notify没有获得锁的线程,就会报错。所以要写成这样:
synchronized(共享数据){
notify();
}
第三次作业
(1)从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略。
第三次作业为多电梯调度,还是采用生产者——消费者模型。
与第二次作业不同的地方在于,由于是多电梯,不光生产者与消费者对共享数据的操作要互斥,消费者与消费者之间对共享数据的操作也要互斥。
请求队列采用二维Arraylist模型,只有每个一维Arraylist的第一个任务可以被电梯接受,每次电梯执行完一个请求就将它从请求队列中移除。
(2)基于度量来分析自己的程序结构度量类的属性个数、方法个数、每个方法规模、每个方法的控制分支数目、类总代码规模计算经典的OO度量画出自己作业的类图,并自我点评优点和缺点,要结合类图做分析通过UML的协作图(sequence diagram)来展示线程之间的协作关系(别忘记主线程)从设计原则检查角度,检查自己的设计,并按照SOLID列出所存在的问题
(3)分析自己程序的bug分析未通过的公测用例和被互测发现的bug:特征、问题所在的类和方法特别注意分析哪些问题与线程安全相关关联分析bug位置与设计结构之间的相关性
mainrequest进入电梯导致超载。我的架构是mainrequest独立于请求队列而存在,因此主请求进入时电梯人数忘了加1。
(4)分析自己发现别人程序bug所采用的策略列出自己所采取的测试策略及有效性,并特别指出是否结合被测程序的代码设计结构来设计测试用例分析自己采用了什么策略来发现线程安全相关的问题分析本单元的测试策略与第一单元测试策略的差异之处
测试策略是猜想哪些地方可能出错,针对性的编写边界测试数据来测试自己程序,debug时采用打印中间信息的方式。
(5)心得体会从线程安全和设计原则两个方面来梳理自己在本单元三次作业中获得的心得体会
由于有些请求不能直达,需要拆分,而拆分的方式又有很多种,而电梯又是根据请求队列来运行的,所以在请求得到时就要进行拆分,我这里采用了傻瓜拆分策略,先看A能否直达,再依次看B,C,再看AB组合,AC,BC依次检索。这里的拆分策略就是一个可以优化的点。
多线程的bug有时候不能复现,所以一组测试数据需要多测几次。
自己写的测试程序的时间不一定是标准的,可以采用研讨课大佬同学讲的标准化时间来输入。