oo第二次博客

来源:https://www.cnblogs.com/16231113-liyilun/archive/2019/04/21/10747267.html
-Advertisement-
Play Games

前言: 這是一篇面向對象作業總結,作業內容是模擬電梯調度,一共有三個階段,具體要求不詳述,第一階段只要求先來先服務電梯,第二次支持捎帶,第三次則需要多部電梯協調,通過換乘來完成請求。本次作業在優化方面效果不佳。設計比較統一,設計原則檢查放在最後。 第5次作業 類圖如下: 說明: 具體的來說,M是主入 ...


前言:

這是一篇面向對象作業總結,作業內容是模擬電梯調度,一共有三個階段,具體要求不詳述,第一階段只要求先來先服務電梯,第二次支持捎帶,第三次則需要多部電梯協調,通過換乘來完成請求。本次作業在優化方面效果不佳。設計比較統一,設計原則檢查放在最後。

第5次作業

類圖如下:

 

 

 

說明:

具體的來說,M是主入口,也是主線程,目的是獲取請求。Loader是容器,也只存在一個單例ld,其中req表是其管理的實質,當要synchronized多個實例時,loader優先上鎖以防死鎖。DianTi則是從屬線程,目的是模擬電梯的運行。

電梯會向loader獲得第一個請求,如果沒有得到就迴圈,直到M放入請求時喚醒它,如果獲得到請求,則先到那個層,然後取得所有當前層乘客,接下來先向上走再向下走,每一層詢問ld有無請求並決定開門與否,其中管理in隊列以獲得請求,直到in隊列空,開始下一輪。輪詢而沒有wait()。

這裡涉及到一個監視器,就是結束標誌,它封裝於loader內部的mainEndFlg,當M結束時設置mainEndFlg,電梯如果沒得到請求又發現M已經結束,則將自己結束了。

       類圖中的另外兩個是用於debug的,模擬測評機進行輸入按時投射。

代碼度量結果如下:

       從度量結果中可以看出,我沒有用子類,這次環複雜度沒標紅,而是嵌套塊深度深了點,主要體現在dianTi的run方法,其抽象還不夠。

Bug:

在強測時出現了bug,原因是輪詢之前沒有將進行goup()和godown(),乘客被鎖在電梯里。

 

第6次作業

類圖如下:

 

說明:

       本次作業與之前一次作業改動不大,具體來說就是添加了一層過濾輸入,使得樓層內部表示是-2,-1,0,1~16,輸出樓層的修正是在dianTi內部函數完成,因為輸出必然只有dianTi才能控制。

       第二點就是wait和notify。本次作業新增了nextTo,作為一個監聽器,當沒有請求時電梯通過nextTo.wait()進入睡眠,當有請求來到ld時,nextTo.notifyAll()喚醒所有進程。這些都封裝於loader內部。

       優化不理想的原因在於每次電梯詢問請求時ld都將其指向人數最多的一層,這在隨機情況下統計特性(可能)不如走到最近一層。

度量分析:

 

這一次我將dianti的run方法進行了一點抽取,所以發現沒紅。7個靜態方法都是一些輔助debug和計算max、min、abs的程式,總方法比之前多了,變為52個。

環複雜度最高的時goDown和goUp,這兩個是功能性方法,攤平有助於修改。不過它們確實是細粒度的並行。

Bug:

第一個bug就是因為沒有考慮0層不可達,通過添加一個類解決之。第二就是CPU輪詢時間太長,通過wait解決之。第三個bug沒體現出來,留在下一次作業中。

第7次作業

    類圖如下:

說明:

       這次作業需要考慮多部電梯協調、不可達樓層以及乘客換乘的問題。這裡加了一層reqDistri,也是一個線程,其實也可以省略,因為計算量並不算太大,它存在的目的是為了對M的輸入進行處理,由乘客請求得出一條可達路徑,插入ld隊列。

一開始使用弗洛伊德演算法,發現最多兩次換乘,後期加入preSche層,原理是獲得每個電梯當前狀態的臨時展板dianTiData,然後由起點和終點之間依次嘗試插入每一層,用一些啟髮式的方法決定路徑。

加入pair輔助類,拓展了myPerson的內容,使之涵蓋了一條請求路徑,但是沒有直接將其分給哪個電梯,ld是被動等待請求的,電梯則是隨機獲得請求的,通過判斷請求路徑的第一個pair是否是自己可達的來決定讓不讓乘客上電梯。當有電梯去往某一層時,下一個電梯則詢問ld則自動跳過那一層,以期望電梯分散搭載乘客。

       停止條件方面,將mainEndFlg放在reqDistr里,reqDistr在M結束後就結束了,而電梯則是需要所有電梯都結束且不可能再有請求時,才能結束。所以ld還要訪問所有in隊列看看其是否為空,每個電梯通過ld的isEmpty方法知道別的電梯的in是否空,以及ld是否還會再有請求。

       後期為了優化,在每個電梯層數變化時,強行更新ld.req里所有請求的路徑,並通知所有的電梯,以期望電梯能夠更加智能。這樣會對性能有一定提升。

度量結果如下:

       可以看出還是沒有紅色的,不過總代碼行數增加了許多,主要是嘗試了兩種啟髮式的方法,一種就是最短距離的電梯先到,不考慮上下行走狀態,另外一種是考慮上下行並且上下行到底就會等待。其實是第一種的性質比較好,而第二種的假設比較多,如果真正實現了完全預運行,則性能應該會更好,望下次改進。要完成這些,需要一個狀態展示板,牽涉到了很多新增屬性。

Bug:

       如果測試到了需要wait的時候再次進行goUp(),goDown(),然後切換cpu發現有新的請求入隊,接著電梯進入wait模式,然後發現沒有更多的請求去喚醒它,這樣它們就死等下去。解決方法就是再次判斷是否需要wait,並且wait時間不超過5秒。這樣對cpu還是可以接受的。

設計原則檢查

       Single Responsibility PrinciplemainEndFlg和nextTo兩個監視器可以抽離出來,其餘基本是專註於管理自己隊列的程式。

         Open Close Principle:大架構基本不變,有些地方需要加點代碼重構,而更多的功能性要求則是通過添加方法和添加類來實現的。

       Liscov Substitution Principle根本沒有子類,不用替換了。

Interface Segregation Principle:沒有介面

Dependency Inversion Principle:抽象的就abs,getlock和release這些static的方法,其他都是源於細節的構架。所以抽象依賴無從談起。

總結

       覺得多線程最重要的就是生產者和消費者模型,worker thread是其變種。所以有多線程的地方首先看其buffer是什麼,有幾層buffer,在一些對性能要求比較高的圖形學架構上就使用這種多層流水的模式,也是生產者消費者模型的變種。

       輪詢可以交給一個特定的進程(比如jvm)去做,雖然還是要輪詢檢查時間,但是畢竟需要輪詢的線程少,則輪詢效率更高,線程則用wait的機制等待時間就好。

       缺點在於,沒有很好的預模擬程式,並且電梯沒有一個預請求隊列,每個電梯都是隨機搶到哪一層的,所以性能得分不高。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • jQuery 入口函數與 JavaScript 入口函數的區別: jquery的入口函數是在html所有標簽都載入後才執行,而JavaScript的window.onload事件是等到所有內容載入完後才執行。 什麼是事件? 頁面的響應叫做事件 index返回dom元素 get([index]))返回 ...
  • 一. 設計策略 1. 架構設計 三個線程:電梯,調度器,主線程(輸入線程), 採用worker thread,生產者消費者模式。和同學討論,發現有的觀點認為:調度器更像是一個功能的集合,類似一個函數,不像是一個主體,而且線程越少bug一般而言越少,於是調度器不做為線程。也挺有道理。架構圖如下: 其中 ...
  • [TOC] 引入 大家先考慮一個場景, 有一個整形數組, 我們希望通過調用一個工具類的排序方法就能對該數組進行排序. 請看下麵的代碼:   Comparable介面的來龍去脈 通過上面的代碼, 我們能夠輕易地對整形數組進行排序, 那麼如果現在有了新需求, 需要對浮點類型數據進行排序, 排序 ...
  • 多態 什麼是多態 指的是同一類/種事物的不同形態(其實就是繼承關係的表現) 為何要用多態 多態性:在多態的背景下,可以在不用考慮對象具體類型的前提下而直接使用對象 多態性的精髓:統一 這就好比開奧迪車,寶馬車和奇瑞qq,開的都是車,學開車不是學開某一輛車。 父類定義了,以後子類需要使用父類的功能,直 ...
  • 配置類: 調用: ...
  • 上一次我們已經通過代碼,簡單的認識了工廠方法模式,具體的思路請移步到 "設計模式之工廠模式(二)" ,進行查看。這次,讓我們通過設計模式的思想,來好好認識下工廠方法模式。 創建者和產品 所有工廠模式都用來封裝對象的創建。工廠方法模式(Factory Method Pattern)通過讓子類決定該創建 ...
  • log4j log4j log4j.rootLogger=INFO, stdout log4j.appender.stdout = org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target = System.out log4j.app ...
  • 文章首發: "結構型模式:橋接模式" 七大結構型模式之二:橋接模式。 簡介 姓名 :橋接模式 英文名 :Bridge Pattern 價值觀 :解耦靠我 個人介紹 : Decouple an abstraction from its implementation so that the two ca ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...