OO第二章總結
電梯作業終于結束了!!! 這三周作業用多線程模拟搭建電梯的運作,我從開始對多線程的一無所知到結束時的能夠完成一些多線程任務的水準,進步還是蠻大的,盡管過程有點艱難。
一、複雜度與UML圖分析
第一次作業
UML

Person類在本次作業沒有用到,我隻是預留了一個擴充類。MainClass類作為啟動,PassengerQueue類是共享資源類,也就是生産者消費者模式的那個傳送帶。Input是生産者,Elevator是消費者。
複雜度分析
電梯類的WMC很高,也就是循環複雜度很高,代碼有個地方進行了重複循環,有待改善。
第二次作業
類的構造和上次基本沒有差別。
第二次作業問題和上次一模一樣(代碼複用的結果
第三次作業
由于限定了電梯的種類,我便建立了三個電梯類,來是實作類别不同,這種方法有點笨重,可以進行抽象出三種類的公共之處作為一個類,這是有待完善的地方。
三個類的代碼是可重複複用的,寫法過于臃腫了。
代碼量
二、自己程式的BUG
程式的bug主要包括RTLE,CTLE以及單線程的邏輯問題。
1. RTLE
RTLE全稱Real Time Exceed,在這三次作業中,評測機所給的Real Time都很大,一般排程是不會讓程式RTLE的,産生的主要原因就是程式的線程無法停止。
無法停止有兩個原因:一個是程式沒有設定終止條件,無法停下來;另外一個就是可能程式裡面出現了死循環,比如:電梯卡在某一層一直開關門,或者電梯在-1和1層遊蕩等就會導緻電梯一直運作,而無法停止。
解決也很簡單,在程式的結束增加輸出的語句來判斷Run方法是否結束,然後在每一個循環裡面增加輸出即可。
2. CTLE
這個就很常見了。。。。(在我的程式裡面
CTLE全稱CPU TIme Exceed。CTLE發生也就一個原因,就是發生了輪詢,也就是一直進行判斷是否滿足條件,導緻CPU一直在運作。
這樣的bug說排除很簡單,也可能很難。簡單就是他産生原因很簡單也很明顯,說難就是它的出現可能是多線程随機的問題,很難複現。
我的排除方法就是仔細分析單線程的邏輯問題。畢竟輪詢就是一個循環,一直在詢問,那麼程式裡面一定會出現類似死循環的情況。在第三次作業裡面通過這種方法,找到了bug出現的原因。另外一個方法就是努力去複現,因為有的死循環,可能是在某一個情況才出現,然後導緻輪詢。複現方法和RTLE一模一樣。
3. WA
wa的情況就自己的程式一般邏輯的問題,很容易去複現,找到問題,解決即可。一般都是寫代碼時的馬虎與不注意。
三、互測
互測找到别人的bug,我是靠自己寫代碼時的經驗與經曆,來構造特定的bug然後hack别人。
四、設計政策
1. 單部可攜帶ALS電梯
第一次作業的設計就很簡單,隻是一部電梯。我采用了生産者和消費者模式。
由于輸入是實時的,我便設定了一個輸入線程作為生産者,将請求添加到主請求(排程器)裡面。單部電梯從主請求裡面擷取一個請求,然後運送,運送過程中如果遇到順路的請求就順路接到電梯。
兩個線程的公共資源是主請求,在使用時需要對齊進行加鎖,保證唯一使用。
2.多部可攜帶ALS電梯
第二次作業的設計是在第一次的基礎上增加動态電梯線程建立和人數的限制。電梯線程的邏輯基本都一樣。
這次電梯線程增加,一個輸入線程作為生産者,多個電梯線程作為消費者,在每一個電梯在進行對主請求的寫操作的時候,都需要加鎖來保證寫的唯一性。是以相比第一次作業這次電梯線程邏輯,對每一個寫操作進行加鎖。基本邏輯是沒有任何改變的。
3. 多部可攜帶ALS電梯
第三次作業相比第二次作業增加了很多的限制條件,限定了電梯的可停靠樓層,限定了電梯的種類等,同時需要滿足動态增加電梯的需求。
這次作業我實作了我前兩次作業一直想要實作的一個Person類,用來擴充輸入接口提供的Request類。因為前兩次都沒有必要去實作,也就沒有實作,但這次電梯需要考慮進行換乘,是以就需要擴充Request類來增加能夠更新需求的狀态的操作。在實作Person類之後,我發現一切都變的和第二次作業如此的相似,我需要做的隻是把需要換乘的人們在第一階段之後進行更新狀态即可。同時由于對電梯的可停靠樓層的限制,我不得不重新對線程的同步問題進行重新設計。
重構了線程終止的條件,同時改變線程等待的條件,并在每一個新增加需求之後喚醒每一個電梯線程,在沒有需求的時候,便讓他們進行休息。
可擴充性
第三次作業的可擴充性,可以支援動态删除電梯,可以動态啟動電梯線程,隻要是關于電梯的新的需求,需要改變的僅僅的頂層的一部分,對于電梯的基本運動邏輯是基本不需要任何改變的。
五、心得體會
對于多線程的設計模式,設計方法,設計思路等有了充分的了解,在多線程并發的能力上有了顯著的提高。從開始的一無所知到後來能清晰的認識到電梯的運作過程,并精确快速找到bug,真的收獲很多。但是也是能夠清楚的認識到,其實多線程還有很多很多東西有待學習,電梯結束了,但是對多線程的學習剛剛起步。
三次作業的疊代明顯比第一章的作業疊代要簡單很多,并不需要很多的重構,很多代碼都是能夠重複使用的。而且在第一次作業的時候,我已經預料到在疊代的過程中,輸入接口所提供的的Request類是需要被擴充的,才能滿足需求,也就預留了很多小的設計在裡面以友善後來擴充使用。