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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...