本題完成的任務為多部多執行緒可捎帶排程電梯的模擬,電梯系統具有的功能為:上下行、開關門、新增一部可以使用的電梯,電梯系統在某一層開關門時間內可以上下乘客。電梯系統可以採用任一的排程策略,只要保證在一定時間內將所有乘客送至目的地即可。
本題採用的是目的選層電梯,在電梯的每層入口,都有乙個輸入裝置,讓每個乘客輸入自己的目的樓層,所以乙個電梯請求除了人員id,還有這個人的出發樓層和目的樓層。
電梯型別分為a型
、b型
、c型
,在新增電梯時指定型別。初始有3部電梯,編號分別為a
、b
、c
,新增電梯編號為x1
、x2
、……、xn
。三類電梯的開關門時間都分別為0.2s
。
樣例輸入
[1.0]x1-add-elevator-a樣例輸出[2.0]1-from–3-to-2
[2.4060]arrive–1-x1被捎帶請求選擇規則:[2.8070]arrive–2-x1
[3.2070]arrive–3-x1
[3.2080]open–3-x1
[3.2080]in-1–3-x1
[3.6080]close–3-x1
[4.0090]arrive–2-x1
[4.4100]arrive–1-x1
[4.8100]arrive-1-x1
[4.8100]open-1-x1
[4.8100]open-1-b
[4.8110]out-1-1-x1
[4.8110]in-1-1-b
[5.2120]close-1-b
[5.2120]close-1-x1
[5.7120]arrive-2-b
[5.7120]open-2-b
[5.7130]out-1-2-b
[6.1130]close-2-b
其他:
2.2.1 scan排程策略的改進
scan排程策略,使電梯沿乙個方向進行掃瞄,每到達乙個樓層,捎帶當前樓層本電梯可以捎帶(該請求的到達樓層是本電梯可停靠的樓層且電梯此時尚未滿載)的請求,直至電梯到達運動方向上最遠的可停靠層,再轉變運動方向進行掃瞄。簡單來說,理解為電梯在最低和最高可停靠層來回掃瞄,同時捎帶和完成請求。
很明顯,這樣的排程策略很有可能會造成效能的損失,如果運動方向上沒有需要捎帶的請求或者電梯已無法捎帶請求並且目前已在電梯內的請求需要停靠的樓層都在相反方向,則可以立刻調轉方向掃瞄,減少來回的無效路程,這就是***look排程策略***,具體的電梯執行緒實現可見下方的流程圖。(有人可能會說,萬一調轉方向後,原先的運動方向上產生了需要捎帶的請求呢?本人的觀點是,這種情況的確有可能出現,但是電梯無法預知未來,所以只能選擇當前情況下的最優選擇,在大部分情況中,採用look排程的效能要比scan排程好)
2.2.2 電梯執行緒流程圖
2.2.3 換乘策略
由於本次題目的請求並不一定可以由乙個電梯單獨完成,所以需要讓乘客進行換乘。
具體的實現方式是:在personrequest
類的原有屬性fromfloor
和tofloor
上增加finalfloor
屬性,如果該請求不需要換乘,將finalfloor
賦值為0,否則將finalfloor
賦值為tofloor
,將tofloor
賦值為中轉樓層。當該請求到達**中轉樓層tofloor
**時,向排程器的請求佇列中增加乙個新請求,新請求的fromfloor
為中轉樓層、tofloor
為原先的finalfloor
(即該請求所要到達的最終樓層)、finalfloor
為0。具體的換乘策略如下表所示:
fromfloor
tofloor
中轉樓層
-32~14
1-2、-1、231
2~14-31
3-2、-1、213
4、6、8、10、12、14
54、6~1435
16~20
2~14
152~14
16~20
153.1.1 模式定義
生產者(producer)是負責產生資料的執行緒,消費者(consumer)是處理資料的執行緒,當生產者消費者以不同的執行緒執行時,兩者之間的速度差異會引起問題,比如消費者想要獲取資料,資料還未生成;生產者想要交付資料,消費者還無法接收資料。為了解決這種生產者和消費者的強耦合問題,可以讓生產者消費者通過緩衝區(channel)進行通訊,進而消除不同執行緒間處理速度的差異。
通俗來說,生產者將生產的資料直接移交緩衝區,消費者直接從緩衝區中提取需要的資料,兩者不直接互動。
3.1.2 模式結構
3.1.3 本題uml時序圖
設計觀察者類和被觀察者類實現對應的介面
public synchronized void method() // 釋放鎖 用
synchronized
修飾的方法是同步方法,鎖住的物件是this
,也就是呼叫該方法的例項,在生產者-消費者
模式中,鎖住的通常就是共享物件。
在對鎖池和等待池有乙個清晰的了解下,可知絕大多數情況下,可以理解為該同步方法可能改變其他等待池中線程的狀態(使其不再等待)時,才需要在保證執行緒安全的地方加上notifyall()
喚醒等待池中的執行緒。
以下內容引自課件「物件導向程式的需求分析與設計原則-1-分析與設計原則」
5.1.1 srp(single responsibility principle)——單一職責原則
srp原則,顧名思義,就是每個類或方法都只有乙個明確的職責,類職責就是使用多個方法從多個方面來綜合維護物件所管理的資料,方法職責就是從某個特定方面來維護物件的狀態(更新、查詢等)。
如果類或方法的職責過多,會導致類或方法的邏輯難以封閉,容易受到外部的影響,因外部因素的變化而變化。
5.1.2 ocp(open close principle)——開閉原則
ocp原則的含義是對擴充套件開放,對修改關閉。簡單來說,當程式進行擴充套件增加新功能(open)時,不需要修改原有的**(close)。ocp原則能夠使程式的擴充套件性更好,易於維護和公升級。
在使用繼承實現ocp原則的過程中,需要保持好子類和父類之間的互動關係,並使用好介面和抽象類。
5.1.3 lsp(liskov substituion principle)——黎克特制代換原則
lsp原則的含義是任何父類出現的地方都可以用子類來代替,並且不會導致相應類的程式出現錯誤。實現ocp原則的關鍵步驟就是抽象化,而父類與子類的繼承關係就是抽象化的具體實現,所以lsp原則是對實現抽象化的具體步驟的規範。
5.1.4 isp(inte***ce segregation principle)——介面隔離原則
isp原則的含義是乙個介面只封裝一組高度內聚的操作,使用多個隔離的介面,避免封裝多種可選的方案,降低類之間的耦合度。
5.1.5 dip(dependency inversion principle)——依賴倒置原則
dip原則的含義是高層次模組不應該依賴於低層次模組,應該依賴於抽象,針對介面程式設計。
C 物件導向多執行緒程式設計簡介
多執行緒程式設計引發的問題 死鎖 無限延遲 資料競爭等。併發程式設計包括多工 多程序 和多執行緒。使用多執行緒程式設計時需包含標頭檔案,具體測試程式 如下 死鎖問題 下例說明了出現死鎖的情況,當臨界區要求使用2個及以上的互斥鎖時,若加鎖的順序不一致,可能導致死鎖。因此為避免死鎖程式猿要保證加鎖的順序...
C 多執行緒物件導向解決方案
相信很多人都讀過 c 沉思錄 這本經典著作,在我艱難地讀完整本書後,留給我印象最深的只有一句話 用類表示概念,用類解決問題 關於多執行緒程式設計,如果不是特別需要,大多數開發人員都不會特意去觸碰這個似乎神秘的領域。如果在某些場合能正確並靈活地運用,多執行緒帶來的好處是不言而喻的。然而,任何事物都有兩...
C 多執行緒物件導向解決方案
相信很多人都讀過 c 沉思錄 這本經典著作,在我艱難地讀完整本書後,留給我印象最深的只有一句話 用類表示概念,用類解決問題 關於多執行緒程式設計,如果不是特別需要,大多數開發人員都不會特意去觸碰這個似乎神秘的領域。如果在某些場合能正確並靈活地運用,多執行緒帶來的好處是不言而喻的。然而,任何事物都有兩...