oo第二次博客作业

第二单元的oo作业主要为多线程。

一. 从多线程的协同和同步控制方面,分析和总结自己三次作业的设计策略

1. 第一次作业

在第一次作业中,我有三个线程和一个共享对象,输入线程,调度器线程和电梯线程,输入和调度器线程之间有一个共享对象请求队列类。三个线程主要为了之后增加多电梯可扩展。

2. 第二次作业

在第二次作业中,我沿用了上一次的构造,有三个线程,但是将共享对象类简化为了使用线程安全的Vector。在第二次作业中我才真正了解到了线程安全方面的问题,多线程执行的不可预测性需要程序保证运行逻辑,在适当的地方加锁,锁不可以不加,更不可以乱加。为了满足第二次作业捎带的任务,我在第二次电梯中采用的策略为电梯每移动一层就进入wait, 调度器判断当前层是否有可以捎带的任务,分配任务后再唤醒电梯。

3. 第三次作业

在第三次作业中,我仍然为输入,调度器,电梯三种线程。不同的是,电梯此次不需要每运行一层就wait,而是会根据已有的指令继续自动化运行,直至没有已分配的任务才进入wait等待唤醒。调度器的任务是根据当前三个电梯已经分配的指令数目直接分配指令。这样的写法能够降低调度器与电梯线程之间的耦合性,使得代码结构更加清晰,功能区域更加明了。

二. 基于度量分析自己的程序结构

1. 第一次作业

方法度量:

类度量:

类图:

solid原则

SRP(Single Responsibility Principle): 满足,输入只负责输入,调度器只有dispatcher方法分配任务,电梯自行上下和开关门。

OCP(Open Close Principle): 不满足,改写捎带需要改变电梯的运行规则,不满足OCP原则。

LSP(Liskov Substitution Principle): 满足,本次作业无继承关系。

ISP(Interface Segregation Principle): 满足,本次作业未使用接口。

DIP(Dependency Inversion Principle): 不满足,本次作业调度器类与电梯类相互依赖,不应该将其直接置于构造函数中,而应该使用set等方法。

2. 第二次作业

方法度量:

类度量:

类图:

 与第一次类图相比,第二次减少了共享对象,改为直接使用java自带的线程安全数据结构。

solid原则

SRP(Single Responsibility Principle): 基本满足,输入只负责输入,判断是否可以捎带写在了电梯里。

OCP(Open Close Principle): 不满足,未对可能出现的不可停靠层处理,第三次作业需要改写电梯类。

LSP(Liskov Substitution Principle): 满足,本次作业无继承关系。

ISP(Interface Segregation Principle): 满足,本次作业未使用接口。

DIP(Dependency Inversion Principle): 满足,本次作业输入依赖调度器,调度器依赖电梯,层层递进,满足依赖关系。

3. 第三次作业

方法度量:

类度量:

类图:

 与第二次作业相比,实现了真正的电梯独立运行,每层停靠不依赖调度器唤醒。

solid原则

SRP(Single Responsibility Principle): 满足,输入只负责输入,调度器只负责给不同的电梯分配任务,电梯自行上下和开关门。

OCP(Open Close Principle): 基本满足,本次电梯有很多设置参数的函数,方便改写和增加新功能。

LSP(Liskov Substitution Principle): 满足,本次作业无继承关系。

ISP(Interface Segregation Principle): 满足,本次作业未使用接口。

DIP(Dependency Inversion Principle): 满足。

三. 分析自己的bug

1. 第一次作业

第一次作业较为简单,我的程序和组内的程序均无bug。

2. 第二次作业

第二次作业恰逢假期,无论是设计还是实现都非常仓促,所以在公测得到了史上最低分。

我在公测和互测中的bug均与线程安全无关,都是由ALS 主任务更换有误,导致电梯完成任务时间过长导致的。

问题所在类都是电梯类,和主请求更换方法,这与我在设计时未进行各类数据的思考和全面的考虑有关。

3. 第三次作业

第三次作业设计较为全面,并进行了充分的测试,我的程序在公测和互测中均无bug。

四. 分析自己发现别人程序bug所采用的策略

黑箱测试,由于目前的代码已经较为复杂,而且多线程的bug也很难直接肉眼发现,所以个人认为黑箱测试是最为有效的检测方法。

与第一单元不同的是,第一单元可以构造非法的特例数据来判断程序是否完成了某项功能,而第二单元没有非法数据。另一方面,第二单元的多线程程序比第一单元更难通过直接分析代码结构来发现bug。

五. 心得体会

1. 线程安全

(1)可以直接使用现成的线程安全数据结构来避免自己写共享对象出现bug。例如用Vector代替ArrayList, 用ConcurrentHashMap代替HashMap等。

(2)wait应该是有条件的,而不是执行到某处直接进入wait,这样容易造成线程安全问题。且需要注意wait的条件中使用线程安全的数据。

2. 设计原则

 在动手写代码前,应该自己手画出程序的uml类图分析逻辑,层次化设计编程。

原文地址:https://www.cnblogs.com/wjyi/p/10741508.html