OO第二单元作业总结
一:設(shè)計策略
第一次作業(yè):第一次是單電梯傻瓜調(diào)度策略,因此我把調(diào)度器當(dāng)作共享資源對象,有一個put和一個get方法,因為只有一個電梯,并且單次取出和投放一個請求,因此只需要同步控制一下這兩個方法是互斥就行了。
第二次作業(yè):第二次作業(yè)是單電梯ALS調(diào)度策略,為了我的代碼能復(fù)用到第三次作業(yè),這次我的調(diào)度器的作用就是把指令全部投放到電梯里,電梯拿到這些指令后,開始獨立的決定自己的方案并執(zhí)行,如此一來,第三次多電梯作業(yè)只需要寫一個調(diào)度器分配請求給各個電梯的方法就行了,第二次的電梯類可以直接復(fù)用過去。基于以上的策略,可以發(fā)現(xiàn)同步控制的工作和第一次一模一樣。
第三次作業(yè):第三次是多電梯智能調(diào)度策略,由于作業(yè)二的準(zhǔn)備(參考上段),本次只需要寫一個分配指令給電梯的調(diào)度器。雖然這次是多電梯,調(diào)度器是共享資源,但是調(diào)度器是主動分配任務(wù)的,因此只需要同步控制電梯內(nèi)請求隊列的訪問即可,不可同時對電梯內(nèi)的·請求隊列投放請求以及刪除請求等。同時由于輸出方法是線程不安全的,多個電梯可能同時輸出信息,因此需要對輸出方法進(jìn)行同步控制。
?
二:基于度量分析自己的程序結(jié)構(gòu)
第一次作業(yè)類圖以及度量圖:
?
?
類圖分析:從類圖分析,第一次作業(yè)類就三個類,主線程進(jìn)行輸入,一個電梯類,一個調(diào)度器類,第一次作業(yè)直接采用經(jīng)典的生產(chǎn)者消費者模型,結(jié)構(gòu)簡單,類較少,每個類的方法也少,每個方法的控制分支數(shù)目少,且每個類的總代碼規(guī)模小。
復(fù)雜度分析:整個程序的ev(G),iv(G),v(G)都較低,說明這次的作業(yè)的程序圈復(fù)雜度低,結(jié)構(gòu)化程度高,高內(nèi)聚,低耦合。同時分析每個類的Ocavg以及WMC容易得到類的方法的平均循環(huán)復(fù)雜度和總循環(huán)復(fù)雜度低。
?
第二次作業(yè)類圖以及度量圖:
?
?
類圖分析:從類圖可以看出,第二次作業(yè)優(yōu)點是:電梯實現(xiàn)了模塊化,即電梯封裝成了一個單獨的可獨立處理請求的模塊,代碼復(fù)用性好。但是缺點也很明顯:電梯內(nèi)的方法較多,個別方法的規(guī)模較大,其實是因為電梯內(nèi)實現(xiàn)了自己的策略調(diào)度算法,以便減輕主調(diào)度器的算法復(fù)雜度并使得實現(xiàn)模塊化設(shè)計智能調(diào)度電梯,但是調(diào)度算法解耦做的不是很好。
復(fù)雜度分析:程序的ev(G)(除了個別方法稍稍高)都較低,說明程序模塊化設(shè)計方面還說得過去。代碼iv(G)部分,除了Lift中的take和backtake方法的iv(G)較高,其他模塊的iv(G)都很低,這兩個方法是調(diào)度策略的核心部分,由于backtake是take的一種特例,因此在take中調(diào)用backtake,使得這兩方法耦合度較高。程序的v(G)方面,依然是Lift中的take和backtake方法的v(G)高,其他方法很低,原因是這兩方法是調(diào)度策略的核心部分,尤其是take方法,由于調(diào)度算法較復(fù)雜,使用了較多的if語句嵌套和for語句嵌套,使得它們的圈復(fù)雜度高。同時分析每個類的Ocavg以及WMC發(fā)現(xiàn)唯獨電梯類的方法的平均循環(huán)復(fù)雜度和總循環(huán)復(fù)雜度高,而這兩個復(fù)雜度高的原因還是來自take和backtake方法的圈復(fù)雜度高,說明調(diào)度算法的解耦做的不好。
?
第三次作業(yè)作業(yè)類圖以及度量圖:
?
?
類圖分析:從類圖可以看出,第三次作業(yè)的優(yōu)點:第三次作業(yè)的類較少,就主類,調(diào)度器類,電梯類,類與類之間只進(jìn)行消息交互,每個類都封裝成了單獨的模塊,實現(xiàn)了獨立的功能,整個程序高內(nèi)聚,低耦合。第三次作業(yè)的缺點:第三次作業(yè)復(fù)用了第二次作業(yè)的電梯模塊,因此把第二次電梯模塊的缺點一起帶了過來。
復(fù)雜度分析:模塊的ev(G)基本都很低,個別方法稍高那么一點,說明這次作業(yè)模塊化設(shè)計比較好,代碼的可維護(hù)性好。模塊的iv(G)基本都很低,只有Lift中的take和backtake方法的iv(G)較高,這是因為第三次作業(yè)直接復(fù)用了第二次作業(yè)的電梯模塊,于是把這個去點帶過來了,但是第三次作業(yè)實現(xiàn)的智能調(diào)度器的iv(G)很低,這是不錯的。然后模塊的v(G)和iv(G)的情況一樣,絕大多數(shù)模塊都很低,只有Lift中的take和backtake方法的iv(G)較高,還是復(fù)用的后遺癥。每個類的Ocavg以及WMC的情況同上。從這次可以得到一個教訓(xùn),代碼復(fù)用具有雙面性,雖然代碼復(fù)用真的很爽,但是如果復(fù)用的模塊的模塊化設(shè)計,圈復(fù)雜度等方面設(shè)計的不好的話,這些缺點會一并帶過來。總的來說這次作業(yè)拋開復(fù)用的模塊外,程序的模塊化設(shè)計較好,結(jié)構(gòu)化設(shè)計高,模塊間低耦合,模塊內(nèi)高內(nèi)聚,每個模塊的復(fù)雜度低(v(G))。
?
三:分析自己程序的bug
分析這三次作業(yè)的bug可以看出,自己這三次作業(yè)中公測和互測的bug總數(shù)是呈遞增趨勢的,并且出現(xiàn)的bug都是線程安全方面的bug,下面來具體分析這三次作業(yè)的bug。
第一次作業(yè):第一次作業(yè)很簡單,單電梯傻瓜調(diào)度策略,依據(jù)生產(chǎn)者消費者模型很容易解決,沒有出現(xiàn)什么bug。
第二次作業(yè):第二次作業(yè)強(qiáng)測沒有掛點,但是互測被發(fā)現(xiàn)一個bug了,發(fā)現(xiàn)是arrayList線程不安全,arrayList的一些操作并不是原子操作,后來手動加鎖后解決了這個問題。
第三次作業(yè):這次作業(yè)強(qiáng)測掛了兩個點,依然是cpu時間超了,仔細(xì)檢查發(fā)現(xiàn)是在有些不該加鎖的地方加鎖了,某種特定情況下三個線程競并且等待導(dǎo)致cpu時間超了。
? 綜合上述分析發(fā)現(xiàn),這三次的bug都是線程安全方面的bug,其中第二次作業(yè)還因為arrayList線程不安全導(dǎo)致的bug給了我一個啟示就是寫多線程的時候,不光要思考自己代碼的邏輯的線程安全,還要注意自己使用的別人提供的方法的線程安全問題。
?
四:分析自己發(fā)現(xiàn)別人程序bug所采用的策略
第一次互測,使用自己寫的評測機(jī),由于第一次作業(yè)過于簡單,并沒有發(fā)現(xiàn)什么bug.
第二次互測,還是評測機(jī),發(fā)現(xiàn)了一些bug但是提交測試用例發(fā)現(xiàn)無法復(fù)現(xiàn)。
第三次互測,這次變聰明了,先使用評測機(jī)發(fā)現(xiàn)會出現(xiàn)bug的測試用例,然后觀察輸出,找出其中的線程安全的bug所在的代碼并分析,設(shè)計使得bug能復(fù)現(xiàn)的測試數(shù)據(jù)。
顯然第三次的策略最為有效,第二種策略使用評測機(jī)發(fā)現(xiàn)bug的測試數(shù)據(jù)的話,由于是線程安全的bug,因此很大可能bug不能復(fù)現(xiàn),因此第三次作業(yè)分析線程不安全的原因,手動構(gòu)造使得bug能復(fù)現(xiàn)的測試數(shù)據(jù)。
?
五:心得體會
這三次作業(yè)的難度是遞增的,對線程安全以及設(shè)計原則的要求也越來越高。首先是第一次作業(yè),由于是單電梯傻瓜調(diào)度策略,故不涉及電梯間資源共享問題,由于單調(diào)度器單電梯,符合生產(chǎn)者消費者模型,故設(shè)計上直接采用生產(chǎn)者消費者模型,從而線程安全基本很容易做到。
第二次作業(yè)還是單電梯,只不過采用ALS調(diào)度策略,設(shè)計上則是調(diào)度器把請求全部丟給電梯,電梯根據(jù)自己的策略決定怎么做。之所以這么做是為了第三次多電梯作業(yè)的代碼復(fù)用,因為如果第二次作業(yè)的電梯實現(xiàn)了給我請求就行了我自己決定怎么做的功能,第三次作業(yè)只需要實現(xiàn)調(diào)度器決定請求怎么分配給這些電梯的功能,可直接把第二次作業(yè)的電梯類復(fù)用過來就行了。線程安全則是和第一次一樣,只有一個電梯,比較簡單,但值得一提的是,第二次作業(yè)我沒想到arrayList線程不安全最終導(dǎo)致我的代碼線程不安全,因此以后多線程不光要考慮自己的代碼線程安全問題,還要考慮點用別人的類以及方法時的線程安全問題。
第三次作業(yè)是多電梯智能調(diào)度。設(shè)計原則上,因為第二次作業(yè)的設(shè)計(見上段),導(dǎo)致這次作業(yè)我只需要思考多電梯的線程安全問題以及調(diào)度器的分配策略即可。現(xiàn)在只剩下線程安全的問題了,這次的線程安全重點在于線程之間的共享資源安全問題以及線程與線程之間的競爭導(dǎo)致的線程安全問題,本次作業(yè)這兩個問題我都考慮并解決了。但是我沒有考慮到電梯之間的并發(fā)導(dǎo)致cpu時間過長的問題,所以這次作業(yè)自己的線程安全是安全,但cpu資源的利用也是很重要的東西,因此兼顧兩者才是真正意義上的線程安全。
綜合三次作業(yè)來說,關(guān)于設(shè)計原則上來說,自己并沒有費很大功夫,相對來說比較簡單,線程安全方面,后兩次作業(yè)都沒有做到線程很安全的地步,但是每次都發(fā)現(xiàn)了自己沒有意識到的可能線程安全問題,使得我的線程一次比一次安全,對線程安全的理解也越來越深,總的來說是在進(jìn)步的,希望以后能做到絕對意義上的線程安全。
轉(zhuǎn)載于:https://www.cnblogs.com/bug2017/p/10764849.html
總結(jié)
以上是生活随笔為你收集整理的OO第二单元作业总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OS X EI Captain 下解决
- 下一篇: 迭代加深搜索 C++解题报告 :[SC