第二單元的三次聯繫做業都寫電梯,要求逐步提升,對於多線程的掌握也進一步加深。本次做業所有都給出了輸入輸出文件,也就避免了正則表達式判斷輸入輸出是否合法的問題。正則表達式
第一次做業,是寫一部電梯的模擬器,指導書提供了一個極爲基礎或者說不叫算法的算法,只須要將人送到正確樓層便可,對於時間、性能沒有任何要求,但也是咱們第一次嘗試多線程,開始寫代碼時對於wait(),notify()函數並非十分了解,致使出現了各類線程不安全,或是出現死鎖的情況,代碼寫得也比較的複雜,架構並非十分清晰。算法
明顯能夠看出run方法複雜度較高,其餘方法爲正常水平。數組
因爲沒有任何性能要求,我採起了接完一我的再去接另外一我的的方法,效率極低,但能夠保證正確性,創建了兩個線程,一個Producer線程,負責讀取輸入,並放入共享隊列中,另個一個Consumer線程,負責處理共享隊列中的指令,並指導電梯上下移動,而在此次做業中我將電梯和Consumer寫在了一塊兒,也就是沒有調度器線程,而只有生產者、消費者。安全
在後期,我也遇到了一些問題,好比結束程序的問題,我在Ctrl D後,並不能結束進程,而是卡在了一些死循環或是wait裏,最終我也在用了信號量的狀況下多加判斷,結束進程。多線程
第二次做業,與第一次做業要求並沒有太大差異,只是增長了地下樓層,也就是負數樓層, 但在性能上有所要求,指導書給出了ALS算法,即捎帶算法,在電梯運行過程當中捎帶路過樓層的乘客,相較於第一次做業的FAFS算法,有了很明顯的進步,性能大大提升,難度也有所提升。輸入輸出接口仍然給好了jar文件,無需咱們擔憂。下面先看一下IDEA對於我代碼的分析。架構
方法複雜度函數
複雜度較高的幾個方法中都包含了較多的if條件判斷,爲確保正確性,只能以性能換正確。代碼設計並非十分到位。性能
第二次做業,我按照指導書使用了ALS算法,每到一個樓層,我會先讓進程sleep(400),以度過開關門時間,而後檢測電梯的等待隊列中,是否有當前樓層的乘客在等待,如有則進入電梯乘客隊列,接着遍歷電梯乘客隊列,將到達樓層爲當前樓層的乘客送出電梯,每一次電梯運動前,都會更新一下當前的目標樓層,目標樓層也會綜合考慮等待隊列中的出發樓層,而後電梯根據目標樓層選擇向上運動或向下運動,每運動一層爲一個週期。測試
我認爲此次做業的難點也就主要在調度一塊,如果調度算法太差會致使Real-Time-Limited-Exceed,如果暴力輪詢不sleep()會出現CPU-Time-Limited-Exceed,這也是我後面本身試出的一個小技巧,因爲對於wait(),notify()兩個方法的理解不到位,個人電梯內部採用暴力輪詢,以防止錯過任何一條指令或是進程在等待i隊列還有指令的時候就結束。 可是我在獲取指令的進程中採用了notify(),以喚醒get()方法中的wait()。spa
第二次做業我並非十分紅功,因爲我的架構太失敗,致使調度環節出問題,電梯運行方向並不會正確的改變,致使在強測時掛了多組數據,未能進入互測,此次做業我吸收了教訓,知道一個不正確的架構,必定寫不出一個正確的程序,在開始碼代碼前必定要考慮周全,想到程序運行的每一方面,尤爲是結束進程方面,必定要在開始之初就設置好信號量,作好規劃,而不能等到寫完程序後在程序內部打補丁,強行結束程序。
第三次做業提升要求,設置爲三部電梯,且每臺電梯可以到達樓層互不相同,也就致使了須要乘坐兩臺電梯才能到達目標樓層的操做,且每臺電梯運行速度,最大承載量也不相同,一開始我想使用繼承,一個父類電梯包括電梯全部操做,而後用子類修改電梯的各類數據,造出三臺電梯,但後來我發現了更加直接的方法,使用構造方法來肯定電梯的幾個參數,無需使用繼承,且繼承run方法我也不太肯定是如何運行的。下面先看下IDEA的分析。
方法複雜度
複雜度高的函數如Tray.get(),由於三臺電梯不一樣,致使獲取的目標也不一樣,也就是用了if判斷語句,增長了複雜度,但之後可使用數組,傳入index以減小if的使用,而在獲取aimFloor一塊,依然複雜度極高,畢竟有多種狀況,我只能使用if判斷,手動判斷狀況。
第三次做業我仍是使用了生產者-消費者模式,因爲會出現一臺電梯沒法送達的狀況,我選擇在當初將指令放入等待隊列時,便拆分好,我會考慮全部的中轉樓層,選取其中路線最短的中轉樓層,而後將前一條指令先放入恰當的電梯中,後一條指令放在個人Monitor線程中,這是我新開的一個監視者線程,負責查看出電梯人員中,是否有id與監視者的等待隊列中的id相同,如有,則該等待隊列中的指令放入適當的電梯等待隊列中,其餘的架構都與第二次做業都差很少。
第三次做業的強側表現也不太好,在這裏我分享一下我debug的經歷,我頻繁出現CPU-Time-Limited-Exceed的問題,根據以往的經驗判斷,必定是暴力輪詢沒有sleep致使的,但我也並非很清楚是哪個while循環出現的暴力輪詢,因而我才用輸出debug的方法,在每個while循環內部都都增長了輸出,「XXX(類名):XXX(方法名) Here!」, 以判斷哪個while出現暴力輪詢,固然輸出結果極其恐怖,一個txt文件裏面有25w+行的輸出,顯然找到了bug所在,可是本身在課下測試時並無仔細測試。
這一次的經歷也教會了我使用JProfiler,能夠在Thread模塊,查看是否有block,如果出現block,即代碼內容有問題,而後使用輸出debug,找到bug所在。