301
社区成员
发帖
与我相关
我的任务
分享这是lcy的面向对象第二单元总结,总体而言这个单元不难,但是做的挺失败的,各种bug层出不穷,居然有一次还没进互测QAQ(开头先小小抱怨一下)
本文将展示如下几个方面:
1,整体结构与协作关系
2,多线程中的锁与同步块
3,调度策略
4,双轿厢相关
5,bug与debug
6,心得体会

这是总体类与内部实现,从左至右依次为从高到底控制的几个线程:主线程,输入,分配器,电梯
以及一些数据类型,如乘客,重置请求
以及控制策略

这是协作图
可以展示出这次作业的总体协作关系
总体上使用了生产者消费者模式,没什么亮点,结构十分经典。
这是这次作业实现的基础。对于线程间共享的数据,为了避免同时读写导致的异常,需要给数据加锁,使得一个数据在某一时刻只能被特定类使用
这就是synchronize块,拿到锁的块可以执行,拿不到就等。
一个块用完了数据必须用notifyAll唤醒其他正在等待的线程。
这里很值得研究的一个问题是:锁与同步块很容易出现死锁与唤醒不了的问题,比较经典的就是第二次迭代中,情景如下:
所以,解决方案是什么呢,如下两条:
感觉这个部分还是很有意思的,之后还需要接着学习QAQ
主流无非就三种:look,als,影子电梯
我用了look
这里有一个很重要的事:三种策略其实性能大差不差,都有自己的弱点,都可以针对hack
所以如果有后来看到我这个博客来写作业的同学,请不要太过纠结自己的策略
言归正传,look策略如下:
是不是很简单?简单且有效嘿嘿
还有一部分是分配策略,就是把人放到哪个电梯的问题,这里我直接暴力分配,%6分配法,甚至能有效解决围师必阙的问题
这里我用了原创方案:双轿厢联动
百年难遇的天才,完美的一二三号位(bushi)
简单讲就是,两个电梯公用一个线程,同时判断开门,同时判断移动
注意这里用词是同时,不是同步!!!!
其实本质就是一个把单电梯要做的事情翻倍了,伪代码如下
(循环)
{
a电梯判断上下
b电梯判断上下
统一输出
更新策略类
a电梯判断方向
b电梯判断方向
ab电梯移动
统一输出
}
高效而简单,甚至复合高内聚低耦合的设计要求!!!
优点在于结构简单了不少,缺点就是如果一个开门一个不开门,那不开门的电梯要干等
但其实性能差不了多少,有时候甚至还快
至于不碰撞的方法嘛,他俩就是一个线程,用同一个策略类分析,怎么可能撞?
bug主要都在锁上,要么就是没加锁,要么就是没唤醒,跑一遍就全出来了
先设计,后动手!!!这样bug真的少了不少
唯一一个很难受的就是:

reset类,获取电梯最大人数(getCapacity),return的是id呜呜呜
idea的回车害了我
到这里其实已经没什么可以说的了
谈两件事吧
这是不出bug的基础。如何保证线程安全?那就一定要记清楚哪里要用锁,哪里用了锁,哪里需要唤醒
这本质上就是一个避免冲突的过程
菜就多练,输不起就别玩
多用几次自然就知道怎样是安全的
这就是战略眼光的部分了:提前想好,如果我要加如功能,该怎么加
最好的添加莫过于在接口里多implement一个类,然后什么都不用改。那这就涉及到层次化了:这次代码从顶向下依次为:主类,输入,分配器,电梯。
那么一层一层设计就好咯,写的时候个人觉得有点像递归:先设计接口,输入输出,然后假设其他层次已经设计好了,把当前层的功能设计好,其实不难
(完结撒花)