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