面向对象的程序设计-模块二课程总结
目錄
- 電梯作業(yè)的設(shè)計(jì)策略
- 基于度量的程序結(jié)構(gòu)分析
- BUG分析及測試
- 心得體會(huì)
電梯作業(yè)的設(shè)計(jì)策略
在整體的架構(gòu)上,我三次作業(yè)使用的設(shè)計(jì)策略較為統(tǒng)一,主要的組成部件有:
- 輸入控制線程:用于控制輸入,向主等待隊(duì)列中添加請(qǐng)求(生產(chǎn)者)
- 主控制線程:用于向電梯分發(fā)任務(wù),從主等待隊(duì)列中拿請(qǐng)求(消費(fèi)者)
- 主線程:主線程使用輪詢的方式查看任務(wù)是否全部執(zhí)行完畢,并結(jié)束程序
- 電梯線程:用于運(yùn)行每個(gè)電梯的等待隊(duì)列中的請(qǐng)求
- 主等待隊(duì)列WaitList:一個(gè)線程安全的共享對(duì)象,設(shè)置put和get方法來放入、拿走請(qǐng)求,并使用wait()和notifyAll()來阻塞或喚醒訪問該共享對(duì)象的線程
從具體的策略上講,使用了生產(chǎn)者&消費(fèi)者模型,輸入控制線程和主控制線程構(gòu)成一對(duì)生產(chǎn)者和消費(fèi)者,二者的共享對(duì)象則是主等待隊(duì)列WaitList,這里我們加鎖來保證同一時(shí)間只能有一個(gè)線程訪問該共享對(duì)象,通過wait()和notify()來實(shí)現(xiàn)阻塞和喚醒訪問該共享對(duì)象的線程;
主控制線程向電梯線程分配其執(zhí)行的人員,每一個(gè)電梯具有自己的等待隊(duì)列,而其任務(wù)就是循環(huán)執(zhí)行分配到自己的等待隊(duì)列中的任務(wù),主控制線程和電梯線程之間的共享對(duì)象就是每個(gè)電梯的等待人員隊(duì)列,這里我們同樣加鎖來保證同一時(shí)間只能有一個(gè)線程訪問等待人員隊(duì)列(共享對(duì)象);
- 在單部電梯執(zhí)行任務(wù)的策略上,我使用了LOOK方法,即電梯選定一個(gè)方向運(yùn)送乘客,在執(zhí)行完當(dāng)前方向上的所有任務(wù)后,再更換方向執(zhí)行后續(xù)任務(wù);
- 在人員分配策略上,我將能夠直達(dá)的請(qǐng)求按照一定的規(guī)則分配給對(duì)應(yīng)電梯進(jìn)行處理,在這里需要考慮的問題是各個(gè)電梯的負(fù)載均衡和最終的時(shí)間最優(yōu)。為了將各個(gè)因素綜合考慮,在這里我設(shè)計(jì)了一種根據(jù)電梯和請(qǐng)求的當(dāng)前狀態(tài)進(jìn)行“打分”的分配方式,即根據(jù)電梯是否已滿、電梯是否正在執(zhí)行任務(wù)、電梯目前所處樓層和方向和當(dāng)前任務(wù)請(qǐng)求的匹配程度等幾個(gè)指標(biāo)來為每個(gè)電梯打分,最終將待分配請(qǐng)求加入得分最高的電梯中(但是由于測試不夠&參數(shù)沒調(diào),導(dǎo)致運(yùn)行的效果并不好)。對(duì)于不能直達(dá)的請(qǐng)求,則會(huì)先執(zhí)行前一部分(運(yùn)到中轉(zhuǎn)層),由電梯線程放入大的等待隊(duì)列,再由主控制線程進(jìn)行新一輪的分配。在中轉(zhuǎn)層的選擇上,我結(jié)合了請(qǐng)求的運(yùn)行方向、分配電梯當(dāng)前的運(yùn)行方向和請(qǐng)求發(fā)出的樓層進(jìn)行了分配。
- 程序結(jié)束的判定:輸入線程終止且電梯運(yùn)行完畢。
在具體的判斷上,當(dāng)輸入線程讀取到null時(shí),將一個(gè)信號(hào)量isEnd置位,主線程通過輪詢+Sleep來判斷以下條件:- 信號(hào)量isEnd置位
- 主等待隊(duì)列為空
- 每個(gè)電梯處于空閑狀態(tài)且每個(gè)電梯的等待隊(duì)列、運(yùn)行隊(duì)列均為空
在滿足上述的三個(gè)條件的情況下結(jié)束程序
但是,主線程可能在下述情況下出現(xiàn)錯(cuò)誤的判定:- 最后一個(gè)任務(wù)從主等待隊(duì)列中取出,但還沒有交給電梯的時(shí)候
- 最后一個(gè)任務(wù)不能直達(dá),從電梯中出來而未放入主等待隊(duì)列的時(shí)候
為了避免這樣的情況下程序的提前截止,我讓主線程在Sleep一小段時(shí)間后再次進(jìn)行判斷,只有兩次判斷均能滿足的時(shí)候才會(huì)結(jié)束運(yùn)行。
基于度量的程序結(jié)構(gòu)分析
第五次作業(yè):單部傻瓜電梯
- 復(fù)雜度分析:
本次作業(yè)中,Main由于需要監(jiān)控各個(gè)線程的運(yùn)行狀況并結(jié)束程序,且具有一定的邏輯判斷深度,所以造成了其OCavg指標(biāo)復(fù)雜度較高;
而類Elevator由于需要維護(hù)其兩個(gè)隊(duì)列(運(yùn)行隊(duì)列和等待隊(duì)列),并判斷和執(zhí)行相應(yīng)的任務(wù),單類中執(zhí)行的功能較多,方法間的互相調(diào)用過于復(fù)雜,導(dǎo)致其WMC指標(biāo)復(fù)雜度過高。
- 類圖:
- 根據(jù)SOLID原則進(jìn)行分析:
- SRP:電梯類Elevator需要執(zhí)行的功能較多,類內(nèi)方法互相調(diào)用復(fù)雜,沒有很好地滿足單一職責(zé)原則;
- OCP:由于電梯的調(diào)度策略改變,電梯和調(diào)度器均在后續(xù)進(jìn)行了重寫
- 其他:本次作業(yè)中沒有繼承和接口,無抽象類
第六次作業(yè):單部可捎帶電梯
- 復(fù)雜度分析:
在本次作業(yè)中,同樣是Elevator類設(shè)置的功能過多,導(dǎo)致其WMC復(fù)雜度較高,Main的邏輯判斷深度及復(fù)雜度較高?。 - 類圖:本次作業(yè)的類圖和第五次作業(yè)基本相同,不單獨(dú)列出
- 根據(jù)SOLID原則進(jìn)行分析:
- SRP:同第五次作業(yè),電梯類Elevator需要執(zhí)行的任務(wù)過多;
- OCP:在本次作業(yè)中實(shí)現(xiàn)了單部電梯的LOOK算法,第七次多電梯作業(yè)中的不同屬性和捎帶策略的電梯是在繼承本次電梯的基礎(chǔ)上通過拓展實(shí)現(xiàn)的
- 其他:本次作業(yè)中沒有繼承和抽象類
第七次作業(yè):多部智能電梯
- 復(fù)雜度分析:
- Elevator執(zhí)行功能過于復(fù)雜,Main依然邏輯復(fù)雜度很高(太懶了?)
- Controller類需要監(jiān)控各個(gè)電梯的運(yùn)行狀態(tài),并根據(jù)不同的情況決定其運(yùn)行策略,導(dǎo)致其邏輯判斷的深度過高,在調(diào)試的過程中,這里也確實(shí)出現(xiàn)了很多BUG。
- 類圖:
UML時(shí)序圖分析:
三次作業(yè)的時(shí)序圖基本類似,挑這次作業(yè)的畫了一下- 根據(jù)SOLID原則進(jìn)行分析:
- SRP:Elevator需要實(shí)現(xiàn)的功能過多,沒有很好地遵循單一職責(zé)原則;
- OCP:Elevator實(shí)現(xiàn)基本的LOOK+捎帶策略,ElevatorA/B/C通過繼承父類Elevator來修改其各自可以停靠的樓層和不同的屬性、捎帶策略;
- LSP:父類可以替換子類使用(但是調(diào)度策略不同);
- 其他:本次作業(yè)中沒有實(shí)現(xiàn)接口,無抽象類
BUG分析及測試
我的電梯在本階段作業(yè)的公測和互測中沒有出現(xiàn)BUG(也沒有性能?),一方面是由于本模塊的作業(yè)邏輯結(jié)構(gòu)較為清晰,另一方面使用了一些極端樣例和大量隨機(jī)樣例進(jìn)行了測試。對(duì)于同組同學(xué)的程序,我也沒有發(fā)現(xiàn)太多的問題。
在測試過程中,我使用了自動(dòng)化測試來檢測正確性,也用它來繪制電梯運(yùn)行期間的時(shí)空?qǐng)D,以監(jiān)測電梯的性能,統(tǒng)計(jì)了電梯的運(yùn)行軌跡及負(fù)載(如下):
電梯運(yùn)行時(shí)空?qǐng)D 圖注:
藍(lán)色:A電梯
綠色:B電梯
紅色:C電梯
折線:電梯運(yùn)行軌跡
每個(gè)方形的大小:當(dāng)前電梯內(nèi)人數(shù)
可以看出,在整個(gè)電梯運(yùn)行的過程中,LOOK算法的執(zhí)行情況較好。但是B電梯的負(fù)荷明顯過高,而C電梯的任務(wù)量太少(運(yùn)行時(shí)間短、運(yùn)送任務(wù)少),電梯整體的運(yùn)行圖能夠更加直觀地展示在電梯生命周期內(nèi)的運(yùn)行負(fù)荷,也更易于找出任務(wù)分配的不均衡。
在互測階段,我也為我們組另一位同學(xué)畫出了這樣的運(yùn)行軌跡圖,30S左右輸入的40條左右請(qǐng)求,他的電梯運(yùn)行了160S以上:
從他的電梯運(yùn)行圖中我們也能發(fā)現(xiàn),他的單部電梯在執(zhí)行任務(wù)的過程中使用的算法不是非常合理,例如B電梯出現(xiàn)了大量”折返跑“的情況;多電梯的任務(wù)分配也存在問題,C電梯在程序運(yùn)行期間有長時(shí)間”摸魚“,A電梯亦有空等時(shí)間過長的情況。
心得體會(huì)
線程安全
- 在設(shè)計(jì)時(shí)考慮到線程之間的同步互斥關(guān)系
- 考慮不同線程和共享對(duì)象之間的關(guān)系
- 合理上鎖
- 考慮所有情況,避免不安全的情況出現(xiàn)
設(shè)計(jì)原則
- 首先保證線程安全
- 在設(shè)計(jì)時(shí)充分考慮以后出現(xiàn)的情況,OCP原則
- 設(shè)計(jì)清晰每個(gè)類的職責(zé),遵循單一職責(zé)原則
- 降低類之間的耦合度
- 使用外部工具來進(jìn)行正確性分析和性能評(píng)
轉(zhuǎn)載于:https://www.cnblogs.com/lebway/p/elevator.html
總結(jié)
以上是生活随笔為你收集整理的面向对象的程序设计-模块二课程总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 项目Alpha冲刺(团队)-代码规范、冲
- 下一篇: 派 二分水题