BUAA-OO-Unit2单元博客

万胜豪-20374050 2024-04-19 16:32:18

1.总结分析三次作业中同步块的设置和锁的选择,并分析锁与同步块中处理语句之间的关系

本单元主要采用生产者消费者模式的同步方法,共享对象为乘客的请求表RequestTable

public class RequestTable {
    private ArrayList<PersonRequest> insideTable = new ArrayList<>();
    private ArrayList<Request> requestTable = new ArrayList<>();
    ......

    public synchronized void putRequest(Request request) {
        requestTable.add(request);

        notifyAll();
    }
  ......
    public synchronized Request getRequest(int i) {
        while (isEmpty()) {
            if (inputEnd && sixEmpty) {
                notifyAll();
                return null;
            }
            try {
                notifyAll();
                wait();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (isEmpty()) {
            notifyAll();
            return null;
        }
        Request ret = requestTable.get(i);

        notifyAll();
        return ret;
    }
  ......
}

可以看出,共享对象类RequestTable通过synchronized来实现同步控制,而各个线程只需要调用共享对象的同步方法即可,无需再线程内部和线程间加锁。

2.总结分析三次作业中的调度器设计,并分析调度器如何与程序中的线程进行交互;总结分析三次作业中的调度策略,并分析自己的调度策略是如何适应时间、电量等多个性能指标的

2.1三次作业架构设计的逐步变化和未来扩展能力画UML类图

本单元三次作业迭代过程中,类的定义和数量均未改变,故只展示第三次作业的类图如下:

img

三次作业都使用了最基本的生产者-消费者模式作为作业底层逻辑,InputHandler将输入放到Schedule的列表中,Schedule负责将列表中的乘客请求分发给各部电梯。

具体到调度策略上:除了第一次作业的指派id的调度策略,后两次调度均采用顺序调度的方式进行调度,逻辑如下:

                roundState();
                PersonRequest personRequest = (PersonRequest)request;
                while (elevatorTableList.get(curEle).getStatus() == 0) {
                    roundState();
                }
                elevatorTableList.get(curEle).putRequest(request);
                TimableOutput.println("RECEIVE-" + personRequest.getPersonId() +
                        "-" + (curEle + 1));
//roundState()方法将电梯id依次轮换。

由于乘客请求随机出现,本策略最后效果依然不错。
第三次作业中,我将一个电梯内内置双轿厢电梯,最小化了架构的改变。

2.2画UML协作图(sequence diagram)来展示线程之间的协作关系

协作图关系如下:

img

2.3识别出三次作业稳定的内容和易变的内容,并加以分析

我的架构中,三次作业均无需新增类,但随着问题愈发复杂,类内复杂度还是不可避免的升高了。

  • 面对第二次作业,我在电梯内新增了重置的处理逻辑。
  • 面对第三次作业,我在一部电梯内实现了双轿厢的运行逻辑。
    这样设计的好处在于基本架构不会改变,不会出现新的需求到来后,需要大幅修改自己的交互逻辑的情况,我还是比较喜欢这种设计的。

3.分析自己在第三次作业中是如何实现双轿厢的两个轿厢不碰撞的

正如前文所说,第三次作业我的双轿厢电梯通过单个电梯“模拟”双轿厢电梯实现,两个轿厢不碰撞的逻辑为:

  • 如果当前应该运行的电梯将要到达换乘层,而换乘层有电梯,那么将换乘层的电梯移走之后再移动。

虽然这样的双轿厢电梯的效率有所降低,但在编写代码实现上非常容易实现。

4.分析自己程序出现过的bug以及自己面对多线程程序的debug方法

第一二次作业中,我的程序未出现bug,但在第三次作业中,我对双轿厢电梯的模拟逻辑出现了bug,导致强测出现了RTLE。

分析过后,我认为这是我的设计逻辑导致的:我追求每次迭代的最小改变,但当迭代次数增加时,有一些类的设计会不可避免地变得过于复杂,导致bug的产生。

5.心得体会

本单元多线程的学习基于生产者-消费者模式展开,每次作业迭代过程中我使用了“尽量不改变原逻辑”的最小迭代方法,这种方法有好有坏,面对多次迭代后产生的bug,我应该在未来面对类似问题时加强“迭代设计”。
最后,本单元的学习实验体验还是不错的,感谢助教和老师!

...全文
54 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧