BUAA_OO_第二单元作业总结
程序設(shè)計(jì)策略
第一次作業(yè)
第一次作業(yè)實(shí)現(xiàn)的是FAFS式傻瓜調(diào)度電梯,由于是第一次接觸多線程,難度不是很大。在我的設(shè)計(jì)里,我借鑒了生產(chǎn)者消費(fèi)者模式,設(shè)計(jì)了一個(gè)輸入線程和一個(gè)電梯線程,控制器的設(shè)計(jì)使用了單例模式,維護(hù)了一個(gè)請(qǐng)求隊(duì)列,作為托盤(pán)使用。在運(yùn)行時(shí),輸入線程負(fù)責(zé)向請(qǐng)求隊(duì)列提供請(qǐng)求,電梯線程負(fù)責(zé)拿取請(qǐng)求,并運(yùn)行到指定樓層。這次作業(yè)的缺點(diǎn)是,我設(shè)計(jì)的控制器較為雞肋,其實(shí)質(zhì)只是一個(gè)存儲(chǔ)調(diào)度指令的隊(duì)列,我將具體的運(yùn)行邏輯全寫(xiě)在了電梯里面。由于電梯是傻瓜式調(diào)度,這樣的設(shè)計(jì)在正確性上沒(méi)有出現(xiàn)問(wèn)題,但是導(dǎo)致了擴(kuò)展性很差,使得我在做第二次作業(yè)時(shí)不得不重寫(xiě)了電梯運(yùn)行的邏輯和控制器的絕大部分內(nèi)容。
第二次作業(yè)
這一次作業(yè)要求實(shí)現(xiàn)一個(gè)可稍帶的ALS電梯。由于上述第一次設(shè)計(jì)的缺陷,我重構(gòu)了控制器和電梯邏輯。調(diào)度策略方面采用了近似look的策略。線程個(gè)數(shù)保持不變,輸入線程保持不變,電梯線程進(jìn)行了較大的改動(dòng),我將所有的運(yùn)行邏輯全部剝離,電梯只負(fù)責(zé)進(jìn)行上人、下人、開(kāi)門、關(guān)門、沿運(yùn)動(dòng)方向移動(dòng)一層的原子操作,而控制器負(fù)責(zé)維護(hù)一個(gè)請(qǐng)求隊(duì)列,負(fù)責(zé)所有的請(qǐng)求處理。即電梯每次上行或者下行一層都要向控制器發(fā)送自身狀態(tài),控制器獲取狀態(tài)后,遍歷整個(gè)請(qǐng)求隊(duì)列,選出同方向捎帶的進(jìn)入請(qǐng)求和到達(dá)請(qǐng)求給予電梯,同時(shí)控制器修改隊(duì)列里的請(qǐng)求狀態(tài),將到站的請(qǐng)求刪除。電梯獲取請(qǐng)求后根據(jù)請(qǐng)求內(nèi)容決定是否執(zhí)行上人、下人、開(kāi)門、關(guān)門、沿運(yùn)動(dòng)方向移動(dòng)一層,到了下一層再獲取新的請(qǐng)求。
為了實(shí)現(xiàn)以上邏輯,我電梯里新增了幾個(gè)電梯狀態(tài)參數(shù):最遠(yuǎn)到達(dá)樓層、電梯運(yùn)行方向、空閑位。每次電梯運(yùn)送同方向的人時(shí)修改最遠(yuǎn)到達(dá)樓層。如果到了一次運(yùn)行的最遠(yuǎn)到達(dá)樓層且沒(méi)有同方向的可稍帶請(qǐng)求,那么就將空閑位置位。控制器發(fā)現(xiàn)有空閑電梯時(shí),就會(huì)使電梯向目前的請(qǐng)求隊(duì)列的第一個(gè)請(qǐng)求移動(dòng)。若當(dāng)前請(qǐng)求隊(duì)列為空,則使電梯靜止空等。
這一次作業(yè)我認(rèn)為設(shè)計(jì)的保證了正確性,實(shí)現(xiàn)了不同模塊之間的獨(dú)立性。性能上有待改進(jìn)的是空閑時(shí),可以讓電梯運(yùn)行,而非空等。
第三次作業(yè)
這一次作業(yè)要求多部多線程智能(SS)電梯的實(shí)現(xiàn)。有了第二次作業(yè)的架構(gòu)設(shè)計(jì),這一次作業(yè)的主要任務(wù)就是進(jìn)行了限定人數(shù)、樓層、運(yùn)行速度等新增要求的擴(kuò)展,還有多線程運(yùn)行時(shí)的線程安全問(wèn)題。為了滿足人數(shù)、樓層的要求,我又在電梯類里新增了電梯的樓層、當(dāng)前人員序列,傳給控制器獲取請(qǐng)求時(shí)也增加了這兩個(gè)成員。為了應(yīng)對(duì)請(qǐng)求需要拆分成多部電梯的情況,我將人員請(qǐng)求設(shè)計(jì)成了一個(gè)類,每個(gè)請(qǐng)求在讀入時(shí),按照周轉(zhuǎn)樓層最少的原則進(jìn)行拆分,每個(gè)人員內(nèi)部建立一個(gè)請(qǐng)求隊(duì)列,人員再組成一個(gè)大的請(qǐng)求隊(duì)列。控制器邏輯加入了樓層判斷、人滿判斷,其余同上一次大致相同。同時(shí)在設(shè)計(jì)時(shí)還注意了從請(qǐng)求隊(duì)列里遍歷時(shí),只能判斷每個(gè)人員內(nèi)部隊(duì)列的第一個(gè)請(qǐng)求,這是保證人員必須完成第一個(gè)請(qǐng)求才能換乘電梯,防止出現(xiàn)時(shí)序問(wèn)題。
這一次作業(yè)可優(yōu)化的地方有不少,例如把根據(jù)電梯實(shí)際運(yùn)行情況實(shí)時(shí)切分請(qǐng)求、根據(jù)電梯負(fù)載分配新請(qǐng)求等等。
程序度量分析
第一次作業(yè)
類圖
類復(fù)雜度
方法復(fù)雜度
時(shí)序圖
SOLID設(shè)計(jì)原則評(píng)價(jià):
SOLID原則分析
- SRP:幾乎所有的調(diào)度邏輯全部丟給了電梯類,控制器幾乎無(wú)作用。
- OCP:由于電梯類包含了太多的運(yùn)行邏輯,可擴(kuò)展性較差,分配邏輯擴(kuò)展起來(lái)很困難。
- LSP:沒(méi)有使用繼承
- ISP:未實(shí)現(xiàn)接口類
- DIP:由于采用生產(chǎn)者消費(fèi)者模式,輸入和輸出模塊互不依賴。
第二次作業(yè)
類圖
類復(fù)雜度
方法復(fù)雜度
時(shí)序圖
SOLID設(shè)計(jì)原則評(píng)價(jià):
SOLID原則分析
- SRP:調(diào)度器僅負(fù)責(zé)調(diào)度,電梯僅運(yùn)行進(jìn)行運(yùn)行的原子操作,職責(zé)劃分明確。
- OCP:由于將所有運(yùn)行控制部分從電梯里抽離,所以新增功能時(shí)可以輕松地?cái)U(kuò)展屬性、增添調(diào)度邏輯
- LSP:沒(méi)有使用繼承
- ISP:未實(shí)現(xiàn)接口類
- DIP:輸入和輸出模塊互不依賴,但控制器調(diào)度需要獲取電梯屬性,依賴電梯的具體狀態(tài)。
第三次作業(yè)
類圖
類復(fù)雜度
方法復(fù)雜度
時(shí)序圖
SOLID設(shè)計(jì)原則評(píng)價(jià):
SOLID原則分析
- SRP:調(diào)度器僅負(fù)責(zé)調(diào)度,各個(gè)電梯僅運(yùn)行運(yùn)行的原子操作,職責(zé)劃分明確,互不影響。
- OCP:由于電梯參數(shù)在構(gòu)造方法時(shí)傳入,所以支持新增電梯或者屬性的擴(kuò)展。
- LSP:沒(méi)有使用繼承
- ISP:未實(shí)現(xiàn)接口類
- DIP:輸入和輸出模塊互不依賴,各個(gè)電梯互相不知道彼此存在,調(diào)度器通過(guò)一個(gè)消息類抽象與電梯通信。
bug相關(guān)
個(gè)人bug
在這個(gè)單元作業(yè)中,由于前兩次的調(diào)度策略較簡(jiǎn)單,也沒(méi)有較大的線程安全問(wèn)題,我前兩次作業(yè)都沒(méi)有出現(xiàn)正確性問(wèn)題。但第三次作業(yè)中,我在強(qiáng)測(cè)時(shí)出現(xiàn)了線程安全問(wèn)題。舉例說(shuō)明我的問(wèn)題:處理請(qǐng)求999-FROM-3-TO-2時(shí),先拆分成999-FROM-3-TO-1以及999-FROM-1-TO-2。由于存在同步問(wèn)題,可能導(dǎo)致在1樓換乘時(shí),先輸出IN-999-1-B再輸出OUT-999-1-C的錯(cuò)誤。這說(shuō)明問(wèn)題在于輸出和修改人員狀態(tài)的不同步。在原來(lái)的設(shè)計(jì)中,我實(shí)現(xiàn)的方法是在調(diào)度器修改人員狀態(tài)(在哪部電梯上),同時(shí)將進(jìn)電梯和出電梯的人員以列表形式傳給電梯,由電梯進(jìn)行輸出In和out信息。這就可能導(dǎo)致在一個(gè)線程對(duì)一個(gè)人員狀態(tài)進(jìn)行修改后還未來(lái)得及輸出,另一個(gè)線程就進(jìn)行了下一次操作。
修改措施是增加了修改狀態(tài)的判斷,控制器在修改人員狀態(tài)時(shí),會(huì)判斷人員是否在電梯內(nèi)。若人員已不在電梯內(nèi),則證明已經(jīng)輸出了out,可以修改狀態(tài);否則不修改。
hack相關(guān)
第一次作業(yè)較簡(jiǎn)單,同組都是滿分,沒(méi)有正確性問(wèn)題。第二次作業(yè)開(kāi)始,除了隨機(jī)生成數(shù)據(jù)以外,我hack別人時(shí)采用的策略主要來(lái)自于個(gè)人寫(xiě)程序時(shí)出現(xiàn)的問(wèn)題,有以下幾點(diǎn):1.一層重復(fù)開(kāi)關(guān)門問(wèn)題,這類問(wèn)題往往是判斷是否轉(zhuǎn)向運(yùn)行時(shí)容易出現(xiàn)的,因此構(gòu)造1-2-1這樣的反復(fù)轉(zhuǎn)向數(shù)據(jù)。2.開(kāi)關(guān)門的間隔上人問(wèn)題,這類問(wèn)題主要出現(xiàn)在可能設(shè)計(jì)出了開(kāi)關(guān)門的0.4秒不能上人的問(wèn)題,針對(duì)這一點(diǎn)可以構(gòu)造【0.0】n條請(qǐng)求,【0.4】n條請(qǐng)求這類數(shù)據(jù),若沒(méi)有在邊界時(shí)間帶人,很容易就會(huì)超時(shí)。但由于取消了T_max限制 ,hack他人時(shí),基本也沒(méi)出現(xiàn)正確性問(wèn)題,倒是隨機(jī)生成的簡(jiǎn)單至[0.0]1-FROM-1-TO--1這樣的數(shù)據(jù)hack到了人。
第三次作業(yè)則是hack的重災(zāi)區(qū),不幸中的萬(wàn)幸是我沒(méi)有被hack出來(lái)強(qiáng)測(cè)的錯(cuò)誤,這可能是由于相關(guān)樣例不好構(gòu)造的緣故。由于這次作業(yè)完成的時(shí)間緊張,我主要時(shí)隨機(jī)生成數(shù)據(jù),生成結(jié)果后再交給檢查程序檢查。在查看他人代碼時(shí),我發(fā)現(xiàn)電梯調(diào)度策略多種多樣,問(wèn)題也出現(xiàn)的各種各樣,理清一個(gè)人的思路已實(shí)屬不易,找出程序運(yùn)行的邏輯更是難,所以我只著重查看了兩個(gè)方面,一個(gè)是調(diào)度隊(duì)列的同步問(wèn)題,另一個(gè)是TimableOutput線程不安全問(wèn)題。
這一單元與第一單元的測(cè)試策略相比,著重點(diǎn)從邊界數(shù)據(jù)轉(zhuǎn)移到了線程安全問(wèn)題上,構(gòu)造一些針對(duì)線程安全的數(shù)據(jù)(例如請(qǐng)求拆分、隊(duì)列加鎖、輸出安全等)更容易得分。
總結(jié)
這一單元的重點(diǎn)是多線程相關(guān)問(wèn)題,包括線程安全、線程同步設(shè)計(jì)等。重中之重就是線程安全的確保,在這一單元自己寫(xiě)出的bug無(wú)一不是線程安全導(dǎo)致的時(shí)序同步問(wèn)題。相比第一單元,算法部分減少了,但多線程并發(fā)的問(wèn)題更加棘手。另外的難點(diǎn)是調(diào)試部分,一行行print輸出確實(shí)很考驗(yàn)人的耐心。電梯控制邏輯嵌套也很多,把所有情況分析全面很困難。總之,這一單元充滿了挑戰(zhàn),也讓我收獲不少。希望在之后的面向?qū)ο笳n程學(xué)習(xí)里,我能繼續(xù)努力,考慮更加全面,保證程序的正確性。
轉(zhuǎn)載于:https://www.cnblogs.com/codearning/p/10760479.html
總結(jié)
以上是生活随笔為你收集整理的BUAA_OO_第二单元作业总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用scikit-learn学习主成分分析
- 下一篇: 设计模式三大类及六大设计原则