OO第二单元博客作业

OO第二次单元总结

一、设计策略

1.基本思路

  首先这三次作业总体都是关于电梯,所以电梯肯定要抽象出一个类。然后听老师上课说的,调度器要有一个类。还要一个主线程来开始其他线程,以及一个用来读取输入的线程。

  所以总体我写了四个类。电梯类:模拟电梯运行,持有属性为运行速度,到达楼层,所在楼层,运行方向等,还有自己的Request队列,存放的是在本电梯内的乘客。调度器类:其实相当于负责看管公有属性的一个类,我这里设计的主要是等待队列和结束信号。然后我选择了同步方法,所以基本上都是在这个类里选择了一些方法进行上锁,等同于锁了调度器对应的对象。读入类:这个类也是一个线程,负责不停地从标注输入读入PersonRequest然后放入调度器中,并且负责传递结束信号。主线程Main类负责启动计时器和启动读入和电梯线程。

2.顺带思路

  第五次作业是傻瓜电梯(电梯里只有一个人),第六次作业开始就有了顺带策略。我认为顺带就是在爬楼的时候,在每一层判断是否要带其他人。这个工作被我交给了调度器,然后在每一层增添了get on 和 get off功能。还有一个问题就是什么人可以被携带。这里主要是调度策略比较难,代码书写方面也就是在加几个if else,没有什么难度。在第六次作业的指导书中提供了一种思路,就是分主请求和副请求的思路,我六七次作业都是按照这个思路来写的。后来我想了想,发现我面对这种没见过的电梯(目的选层电梯),做调度策略的时候太过死板。其实虽然我们的代码写的是虚拟的电梯,但是我们现实生活中的方便快捷的电梯运行思路也是值得参考的。如果加入这些思考的话,主请求的更换是提高顺带效率的必要选择,但是我当时的调度策略没有考虑到这方面。结果导致第六次作业的性能分近乎为零。

3.多部电梯的协作

  第七次作业加入了多部电梯,调整了每部电梯的运行速度,最难受的是加入了每个电梯可以抵达的楼层,导致出现了需要转梯的情况。从调度策略的角度,需要合理协调三部电梯,完成转梯,并提高效率。另一方面,增加了两部电梯,从线程安全的角度,又多了一些顾虑,需要更加合理的设置锁。

  像老师说的一样,其实这次作业并没有在调度策略上为难我们,只是想要完成作业而不太考虑效率的话,做法就比较简单。我是找了两个公共层,即所有电梯都可以到达的层,1层和15层。需要转梯的高层统一在15层转,其他的都在1层转。这个调度策略不是很通用,但是在本次作业设置的三个电梯中,在转梯方面是比较合理的,只有个别的请求,比如从3层到14层的请求,会比理想情况多跑个一两层。这次作业我做的比较差的地方是多部电梯协作来提高效率的地方,比如有一名乘客要从1层到20层,所以A电梯先把它接走了,过了一会又有一名乘客要从1层到20层,按我的调度设定,A电梯会过来跑两趟,可是实际上可以让B电梯帮忙先从1层送到15层,这样一会A电梯可以少跑几层,总体时间就变短了。还有因为涉及到电梯的容量,所以会有虽然满足要求但是上不了电梯的乘客,这些乘客也可以让其他电梯帮忙来送一半路程(还是我在看测试样例的时候发现的)。这里我几乎没有写出来,感觉如果考虑到这种情况,调度策略会变得很复杂……

  在线程安全的问题,我前两次作业都是让电梯线程不停的尝试同调度器中读取请求,整个线程中是没有wait,notify这样的。不过因为这次是三个电梯,我为了提高效率,所以用了wait来在合适的时候把线程调到阻塞态。我用的是方法锁,锁的是调度器类的实例,这样的方法其实一直是有安全隐患的,但是因为前两次作业只有两个线程在抢锁,所以我一直没管。由于我在一个线程的一个部分会多次调用调度器中的同步方法,比如会出现条件if后面调用一次,在else if和执行的代码块中又调用一次。那么,可能会导致在这些本来应该连贯的进行的步骤,因为在中途被抢锁,导致被中断。所以这次我综合了同步块和同步方法一起使用。

  除这两个部分,在加入两部电梯的情况下,如何判断是否结束线程成了一个有点难度的问题。等待队列为空,end信号设置和自己的电梯队列为空不再是结束线程的全部条件,因为其他电梯还在运行,而电梯中的乘客可能是一名需要转梯的乘客。而且因为用了wait,所以最后设置每个电梯线程结束时都要再notifyall一下,避免有的线程一直被阻塞着没法结束,而且满足所有电梯内部都没有人,等待队列为空且end信号设置的情况下(即真的结束),不能再wait了。

二、类图分析

第五次作业类图

第六次作业类图

第七次作业类图

 

时序图

 

  我只画了第七次作业的时序图(因为我还不太会画时序图的原因,不额能准确地画出这几次作业时序图的区别)。我觉得我对这几个线程的设计还是比较合理的,基本上能够完成三次作业的基本要求,至于性能上的问题,多出现在调度策略上。

  我看了一些其他人的代码,发现他们有些人会设计更多的类。从度量分析来看,我这次的每个方法规模都不大,但是一个类里含了太多的方法,尤其是调度器类。也许可以再分些小类,但是我没想到要怎么分比较好。

三、bug分析

  公测用例和互测用例均为发现bug

四、互测策略

  其实我这个单元对互测都不是很关注……因为总觉得这个单元能进入强测的代码都太不好找bug了。而且在本地端测试这种需要特定时间投放数据的代码对吾等菜鸡来说太难了。真的很好奇出现hack一百多次的大佬是怎么办到的。

五、心得体会 

  第一次接触线程方面的代码,完全体会到了它的麻烦的地方。也许写的时候思路清晰,想着到时候线程应该怎么跑怎么跑,结果真跑起来完全另一种情况。以前依赖的调试也完全GG,编译器自带的调试完全无法调试多线程,可以说怎么调试都是对的。调试只能用print,真的是非常难受了。设计的时候,要对线程的同步和异步很了解,且清楚每个线程的状态,阻塞态的线程要被唤醒,不然最后结束不了。

  线程安全就是上锁的问题。基本上就是给共享数据上锁,但是上锁涉及到锁的太多效率低,锁的太少锁不住,也很难判断。而且没被锁住的代码也要关注,确定是不会威胁线程安全的地方。

 

转载于:https://www.cnblogs.com/sugarbottle/p/10763769.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值