【C#高級編程(集合2)】 C#高級編程之實現隊列讀寫操作


     實現隊列讀寫操作

概述:集合大家都不陌生,但是實際應用確實有時候讓人無從下手。其比數組最大的好處就是針對多變的動態的元素降服之功能!妙哉,筆者通過《C#高級編程》集合章節發現集合也會“博大精深,變化多端”的。但是有不同於書本,那么大一本厚書,讓人敬而遠之,特別一些些一套套理論的東西更是頭大。筆者准備從集合的列表,隊列,棧,鏈表,有序表,字典,等分系列發布。盡可呢避免大篇理論(核心的還是要強調的)。然后筆者自己做一些小實例,通過自己總結描述設計思想,結合代碼實現,加以重點強調語句。最后配上運行結果!盡可能達到初學者有所悟吧。

C#基礎系列導航


  1. C#實現隊列讀寫操作(一)
  2. 變化多端的列表(二)
  3. VS自動內存管理(垃圾回收集)(三)
  4. C#忽略基礎知識點梳理(四)
  5. 什么是框架的接口(五)
  6. 程序集的加載與反射(六)
  7. CLR寄宿和應用程序域(七)
  8. 異常(八)

【隊列】隊列對元素操作是實現出隊和入隊的原則,又遵循先進先出准則:即先放進隊列中的元素先取出來,這個好比咱們在學校或公司排隊買飯,排在前面的先買到飯,先買到的先離開。諸如此類的例子很多了。而且隊列操作在一些業務邏輯上很重要,就像文件管理操作也可以用隊列實現,待會咱們再用實例演示並加以分析。還有一點就是你在隊列放入一些元素,初始化會分配一個n個大小的空間,當空間不足時候,會自動增長,並且是上一次的兩倍大小。假如第一次分配n,第二次就是2n,第三次就是4n...這個符合集合分配方式,故隊列也是集合一種!

【實例演示】下面做一個文檔管理來演示Queue<T>,一個線程文檔添加隊列,另一個線程讀取隊列。這里面涉及幾個類:

Document類:對文檔屬性和構造方法定義

DocumentManager類:數據入隊出隊即文檔管理

ProcessDocuments類:單獨線程處理隊列中的文檔

【涉及演示思想】

      本實例想通過文檔操作,在隊列中寫入讀取數據,然后咱們借助線程堆文檔處理,以及客戶端如何調用.以前對隊列只是理論方法,不會具體使用,線程這次也派生用場.一例子多用.在Document類通過定義文檔題目和文檔內容和一個帶參構造函數,對文檔類設置.在DocumentManager類中通過AddDocument方法中隊列的Enqueue方法寫進去數據,記得加鎖,在GetDocument方法中加鎖實現Dequeue方法讀取.當然還有判斷什么時候隊列為空,通過IsDocmentAvailiable判斷對中總是是否小於0來判斷是否為空.最后在ProcessDocuments類中,要想從外部啟動進程必須使用start方法,注意,使用前先實例一個進程.利用ProcessDocuments類來啟動線程.不過,run來啟動線程方法.直到隊列中數據為空,跳出while循環,終止進程.

【幾個隊列常用方法】

Enqueue:隊列一端添加元素

Dequeue:頭部取數據和刪除,數據取空拋出異常

Peek:頭部取數據,不刪除

Count:隊列元素個數

TrimExcess:Dequeue或Peek取數據,但不會刪除隊列內存大小,通過此方法重新設置容量,從頭部去除空元素。

Contains:確定隊列是否包含某個元素

CopyTo:元素從隊列復制一個已有的數組中

TpArray:包含隊列中新數組

1 隊列中屬性和構造函數設置:文檔題目,內容,含參構造函數

    /// <summary>
    /// 隊列中屬性和構造函數設置 /// </summary>
    public  class Document { public string title { get; set; } public string content { get; set; } public Document(string title, string content) { this.title = title; this.content = content; } }

2 讀取文檔操作即文檔管理:實例化隊列,並對其進行入隊,出隊,判斷為空方法操作

    /// <summary>
    /// 讀取文檔操作即文檔管理 /// </summary>
    public class DocumentManager { private readonly Queue<Document> documentQueue=new Queue<Document>(); public void AddDocument(Document doc) { lock(this) { documentQueue.Enqueue(doc); } } public Document GetDocument() { Document doc = null; lock (this) { doc = documentQueue.Dequeue(); } return doc; } public bool IsDoctumentAvailable { get { return documentQueue.Count > 0; } } }

3 單獨線程處理隊列中的文檔:設置含對象參數的構造函數,run方法啟動線程,start方法外部啟動線程

    /// <summary>
    /// 單獨線程處理隊列中的文檔 /// </summary>
    public class ProcessDocuments { private DocumentManager documentManager; public ProcessDocuments(DocumentManager dm) { this.documentManager = dm; } public static void Start(DocumentManager dm) { new Thread(new ProcessDocuments(dm).Run).Start(); } public void Run() { while (true) { if (documentManager.IsDoctumentAvailable) { Document doc = documentManager.GetDocument(); Console.WriteLine("線程 目錄{0}", doc.title); } Thread.Sleep(new Random().Next(20)); } } }


4 客戶端調用:實例化文檔管理方法,啟動線程,兩個線程添加讀取數據

        static void Main(string[] args) { DocumentManager dm = new DocumentManager(); ProcessDocuments.Start(dm); for (int i = 0; i < 100; i++) { Document doc = new Document("題目:" + i.ToString(), "內容:"); dm.AddDocument(doc); Console.WriteLine("添加 題目 {0}", doc.title); Thread.Sleep(new Random().Next(20)); } Console.ReadKey(); }


【運行結果】岑參不齊的顯示數據,一個線程添加,一個線程讀取的原因.添加線程添加一個資源后,會釋放資源,讀取線程會讀取.但是他們不是交替的,而是無規律的讀取方式

【疑問和總結】為什么讀取兩個線程?到底機制在何處?

分析一:ProcessDocuments類中start方法來啟動線程,如下操作會正常運行的.

        public static void Start(DocumentManager dm) { new Thread(new ProcessDocuments(dm).Run).Start(); }

分析二:假如start方法中如下設置,先實例化,在啟動線程,最后外部方法調用線程,結果如何?

       public static void Start(DocumentManager dm) { ProcessDocuments pd = new ProcessDocuments(dm); pd.Run(); new Thread(pd).Start(); }

分析結果:分析一正常運行,分析二報錯.因為start啟動前需要實例化一個新線程.調用run方法.分析二傳入的只是一個對象.

到此,關於隊列操作已經結束.接下來會有集合3棧的實例分析和實例演示!由於時間關系,累一天也該休息了.各位晚安!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM