C# 多線程經典樣本 吃蘋果

來源:互聯網
上載者:User
本文主要講述了多線程開發中經典樣本,通過本樣本,可以加深對多線程的理解。

樣本概述:

  下面用一個類比吃蘋果的執行個體,說明C#中多線程的實現方法。要求開發一個程式實現如下情況:一個家庭有三個孩子,爸爸媽媽不斷削蘋果往盤子裡面放,老大、老二、老三不斷從盤子裡面取蘋果吃。盤子的大小有限,最多隻能放5個蘋果,並且爸媽不能同時往盤子裡面放蘋果,媽媽具有優先權。三個孩子取蘋果時,盤子不可為空,三人不能同時取,老三優先權最高,老大最低。老大吃的最快,取的頻率最高,老二次之。

涉及到知識點:

線程Thread 建立並控制線程,設定其優先順序並擷取其狀態。

鎖 lock 用於實現多線程同步的最直接辦法就是加鎖,它可以把一段代碼定義為互斥段,在一個時刻內只允許一個線程進入執行,而其他線程必須等待。

事件EventHandler 聲明一個事件,用於通知介面做改變

設計思路:

Productor 表示生產者,用於削蘋果。

Consumer 表示消費者,用於吃蘋果。

Dish 盤子,用於裝蘋果,做為中間類

EatAppleSmp 的BeginEat()方法,表示開始吃蘋果,啟動線程

-------------------------------------------------------------------------------------------------

如下【爸爸媽媽削蘋果,孩子吃蘋果】:

後台輸出如下:

Mama放1個蘋果Baba放1個蘋果Dage取蘋果吃...Erdi取蘋果吃...Sandi等待取蘋果Mama放1個蘋果Sandi取蘋果吃...Baba放1個蘋果Dage取蘋果吃...Mama放1個蘋果Baba放1個蘋果Erdi取蘋果吃...Mama放1個蘋果Baba放1個蘋果Dage取蘋果吃...Sandi取蘋果吃...Mama放1個蘋果Baba放1個蘋果Erdi取蘋果吃...Mama放1個蘋果Baba放1個蘋果Dage取蘋果吃...Mama放1個蘋果Baba放1個蘋果Sandi取蘋果吃...Mama放1個蘋果Baba正在等待放入蘋果Erdi取蘋果吃...Baba放1個蘋果Dage取蘋果吃...Mama放1個蘋果Baba正在等待放入蘋果Mama正在等待放入蘋果Sandi取蘋果吃...Baba放1個蘋果Mama正在等待放入蘋果Erdi取蘋果吃...Mama放1個蘋果Dage取蘋果吃...Baba放1個蘋果Mama正在等待放入蘋果Dage取蘋果吃...Mama放1個蘋果Baba正在等待放入蘋果Erdi取蘋果吃...Baba放1個蘋果Sandi取蘋果吃...Mama放1個蘋果Baba正在等待放入蘋果Dage取蘋果吃...Baba放1個蘋果Mama正在等待放入蘋果Erdi取蘋果吃...Mama放1個蘋果Baba正在等待放入蘋果Sandi取蘋果吃...Baba放1個蘋果Mama正在等待放入蘋果Dage取蘋果吃...Mama放1個蘋果Baba正在等待放入蘋果Mama正在等待放入蘋果Erdi取蘋果吃...Mama放1個蘋果Baba正在等待放入蘋果Dage取蘋果吃...Baba放1個蘋果Mama正在等待放入蘋果Sandi取蘋果吃...Mama放1個蘋果Baba正在等待放入蘋果Mama正在等待放入蘋果線程 'Mama' (0x1ce0) 已退出,傳回值為 0 (0x0)。線程 'Baba' (0x1888) 已退出,傳回值為 0 (0x0)。Erdi取蘋果吃...Dage取蘋果吃...Sandi取蘋果吃...Dage取蘋果吃...Erdi取蘋果吃...Dage等待取蘋果Sandi等待取蘋果Erdi等待取蘋果

Productor 代碼如下:

  using System;   using System.Collections.Generic;   using System.Linq;   using System.Text;   using System.Threading;      namespace DemoSharp.EatApple   {       /// <summary>      /// 生產者      /// </summary>      public class Productor      {          private Dish dish;          private string name;            public string Name          {              get { return name; }              set { name = value; }          }            public EventHandler PutAction;//聲明一個事件,當放蘋果時觸發該事件           public Productor(string name, Dish dish)          {              this.name = name;              this.dish = dish;          }          public void run()          {              while (true)              {                  bool flag= dish.Put(name);                  if (flag)                  {                      if (PutAction != null)                      {                          PutAction(this, null);                      }                      try                      {                          Thread.Sleep(600);//削蘋果時間                      }                      catch (Exception ex)                      {                       }                  }                  else {                      break;                  }              }          }      }  }

Consumer代碼如下:

  using System;   using System.Collections.Generic;   using System.ComponentModel;    using System.Data;    using System.Drawing;    using System.Linq;    using System.Text;    using System.Windows.Forms;   using DemoSharp.EatApple;   namespace DemoSharp  {      /// <summary>      /// 頁面類     /// </summary>      public partial class EatAppleForm : Form      {         private EatAppleSmp m_EatAppleSmp = new EatAppleSmp();           public EatAppleForm()         {             InitializeComponent();              InitView();              m_EatAppleSmp.PutAction += PutActionMethod;              m_EatAppleSmp.GetAction += GetActionMethod;         }           /// <summary>         /// 初始化GroupBox          /// </summary>          private void InitView()          {              this.gbBaba.Controls.Clear();              this.gbMama.Controls.Clear();               this.gbDage.Controls.Clear();              this.gbErdi.Controls.Clear();              this.gbSandi.Controls.Clear();         }            /// <summary>          /// 啟動線程            /// </summary>              /// <param name="sender"></param>            /// <param name="e"></param>            private void btnStart_Click(object sender, EventArgs e)             {                 this.m_EatAppleSmp.BeginEat();              }                  /// <summary>             /// 放蘋果事件             /// </summary>             /// <param name="sender"></param>             /// <param name="e"></param>              private void PutActionMethod(object sender, EventArgs e)               {                   Productor p = sender as Productor;                  if (p != null)                  {                      if (p.Name == "Baba")                        {                           AddItemToGroupBox(this.gbBaba, this.lblBaba);                        }                       if (p.Name == "Mama")                        {                            AddItemToGroupBox(this.gbMama, this.lblMama);                        }                  }                }                        /// <summary>                /// 吃蘋果事件                /// </summary>              /// <param name="sender"></param>                /// <param name="e"></param>                public void GetActionMethod(object sender, EventArgs e)                {                    Consumer c = sender as Consumer;                     if (c != null)                     {                          if (c.Name == "Dage")                         {                               AddItemToGroupBox(this.gbDage, this.lblDage);                          }                           if (c.Name == "Erdi")                              {                               AddItemToGroupBox(this.gbErdi, this.lblErdi);                             }                              if (c.Name == "Sandi")                                {                                   AddItemToGroupBox(this.gbSandi, this.lblSandi);                              }                            }                       }                                       /// <summary>                      /// 往指定的GroupBox中添加對象                      /// </summary>                        /// <param name="gbView"></param>                        /// <param name="lbl"></param>                       private void AddItemToGroupBox(GroupBox gbView,Label lbl)                       {                              gbView.Invoke(new Action(() =>                            {                                PictureBox p = new PictureBox();                               p.Width = 20;                                p.Height = 20;                               p.Dock = DockStyle.Left;                              p.Image = this.imgLst01.Images[0];                               p.Margin = new Padding(2);                               gbView.Controls.Add(p);                                           }));                             //顯示個數                            lbl.Invoke(new Action(() => {                               if (string.IsNullOrEmpty(lbl.Text))                                 {                                     lbl.Text = "0";  using System;   using System.Collections.Generic;   using System.Linq;   using System.Text;   using System.Threading;     namespace DemoSharp.EatApple  {      /// <summary>     /// 消費者        /// </summary>     public class Consumer     {          private string name;         public string Name        {            get { return name; }           set { name = value; }        }        private Dish dish;          private int timelong;         public EventHandler GetAction;//聲明一個事件,當放蘋果時觸發該事件       public Consumer(string name, Dish dish, int timelong)        {             this.name = name;             this.dish = dish;             this.timelong = timelong;        }        public void run()        {             while (true)            {                 bool flag=  dish.Get(name);                if (flag)                 {                     //如果取到蘋果,則呼叫事件,並開始吃                     if (GetAction != null)                   {                        GetAction(this, null);                    }                     try                    {                        Thread.Sleep(timelong);//吃蘋果時間                    }                    catch (ThreadInterruptedException)                     {                     }                }                 else {                      break;                  }            }        }     } }                                }                                lbl.Text = (int.Parse(lbl.Text) + 1).ToString();                            }));                        }                     }                  }

Dish代碼如下:

 using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.Threading;    namespace DemoSharp.EatApple  {      /// <summary>     /// 盤子,屬於中間類     /// </summary>     public class Dish     {         private int f = 5;//表示盤子中還可以放幾個蘋果,最多隻能放5個蘋果          private int EnabledNum;//可放蘋果總數         private int n = 0; //表示已經放了多少個蘋果          private object objGet = new object();         private object objPut = new object();          /// <summary>         /// 建構函式,初始化Dish對象         /// </summary>         /// <param name="num">表示削夠多少個蘋果結束</param>         public Dish(int num)         {             this.EnabledNum = num;         }         /// <summary>         /// 放蘋果的方法         /// </summary>         /// <param name="name"></param>          ///<returns>是否放成功</returns>         public bool Put(string name)        {            lock (this)//同步控制放蘋果   {   bool flag = false;     while (f == 0)//蘋果已滿,線程等待    {      try         {         System.Console.WriteLine(name + "正在等待放入蘋果");          Monitor.Wait(this);       }       catch (Exception ex) {    System.Console.WriteLine(name + "等不及了");    }  }   if (n < EnabledNum)  {   f = f - 1;//削完一個蘋果放一次     n = n + 1; System.Console.WriteLine(name + "放1個蘋果");  flag = true;      }  Monitor.PulseAll(this);        return flag;      }      }       /// <summary>       /// 取蘋果的方法        /// </summary>        /// <param name="name"></param>       public bool Get(string name)       {         lock (this)//同步控製取蘋果           {             bool flag = false;               while (f == 5)              {                  try                  {                       System.Console.WriteLine(name + "等待取蘋果");                      Monitor.Wait(this);                    }                    catch (ThreadInterruptedException) { }   }      if (n <= EnabledNum)      {             f = f + 1;          System.Console.WriteLine(name + "取蘋果吃...");             flag = true;           }              Monitor.PulseAll(this);            return flag;     }     }   } }

EatAppleSmp代碼如下:

 using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.Threading;    namespace DemoSharp.EatApple  {      public class EatAppleSmp     {         public EventHandler PutAction;//聲明一個事件,當放蘋果時觸發該事件        public EventHandler GetAction;//聲明一個事件,當放蘋果時觸發該事件         /// <summary>         /// 開始吃蘋果        /// </summary>         public void BeginEat()        {          Thread th_mother, th_father, th_young, th_middle, th_old;//依次表示媽媽,爸爸,小弟,二弟,大哥             Dish dish = new Dish(30);             Productor mother = new Productor("Mama", dish);//建立線程             mother.PutAction += PutActionMethod;             Productor father = new Productor("Baba", dish);            father.PutAction += PutActionMethod;           Consumer old = new Consumer("Dage", dish, 1200);             old.GetAction += GetActionMethod;            Consumer middle = new Consumer("Erdi", dish, 1500);            middle.GetAction += GetActionMethod;            Consumer young = new Consumer("Sandi", dish, 1800);            young.GetAction += GetActionMethod;             th_mother = new Thread(new ThreadStart(mother.run));            th_mother.Name = "Mama";            th_father = new Thread(new ThreadStart(father.run));             th_father.Name = "Baba";             th_old = new Thread(new ThreadStart(old.run));             th_old.Name = "Dage";             th_middle = new Thread(new ThreadStart(middle.run));            th_middle.Name = "Erdi";            th_young = new Thread(new ThreadStart(young.run));            th_young.Name = "Sandi";             th_mother.Priority = ThreadPriority.Highest;//設定優先權             th_father.Priority = ThreadPriority.Normal;            th_old.Priority = ThreadPriority.Lowest;            th_middle.Priority = ThreadPriority.Normal;            th_young.Priority = ThreadPriority.Highest;             th_mother.Start();             th_father.Start();             th_old.Start();            th_middle.Start();            th_young.Start();         }         private void GetActionMethod(object sender,EventArgs e)         {             if (GetAction != null)            {                 GetAction(sender, e);             }         }         private void PutActionMethod(object sender, EventArgs e)        {            if (PutAction != null)             {                 PutAction(sender, e);             }         }     }}

介面類代碼如下:

  using System;   using System.Collections.Generic;   using System.ComponentModel;    using System.Data;    using System.Drawing;    using System.Linq;    using System.Text;    using System.Windows.Forms;   using DemoSharp.EatApple;   namespace DemoSharp  {      /// <summary>      /// 頁面類     /// </summary>      public partial class EatAppleForm : Form      {         private EatAppleSmp m_EatAppleSmp = new EatAppleSmp();           public EatAppleForm()         {             InitializeComponent();              InitView();              m_EatAppleSmp.PutAction += PutActionMethod;              m_EatAppleSmp.GetAction += GetActionMethod;         }           /// <summary>         /// 初始化GroupBox          /// </summary>          private void InitView()          {              this.gbBaba.Controls.Clear();              this.gbMama.Controls.Clear();               this.gbDage.Controls.Clear();              this.gbErdi.Controls.Clear();              this.gbSandi.Controls.Clear();         }            /// <summary>          /// 啟動線程            /// </summary>              /// <param name="sender"></param>            /// <param name="e"></param>            private void btnStart_Click(object sender, EventArgs e)             {                 this.m_EatAppleSmp.BeginEat();              }                  /// <summary>             /// 放蘋果事件             /// </summary>             /// <param name="sender"></param>             /// <param name="e"></param>              private void PutActionMethod(object sender, EventArgs e)               {                   Productor p = sender as Productor;                  if (p != null)                  {                      if (p.Name == "Baba")                        {                           AddItemToGroupBox(this.gbBaba, this.lblBaba);                        }                       if (p.Name == "Mama")                        {                            AddItemToGroupBox(this.gbMama, this.lblMama);                        }                  }                }                        /// <summary>                /// 吃蘋果事件                /// </summary>              /// <param name="sender"></param>                /// <param name="e"></param>                public void GetActionMethod(object sender, EventArgs e)                {                    Consumer c = sender as Consumer;                     if (c != null)                     {                          if (c.Name == "Dage")                         {                               AddItemToGroupBox(this.gbDage, this.lblDage);                          }                           if (c.Name == "Erdi")                              {                               AddItemToGroupBox(this.gbErdi, this.lblErdi);                             }                              if (c.Name == "Sandi")                                {                                   AddItemToGroupBox(this.gbSandi, this.lblSandi);                              }                            }                       }                                       /// <summary>                      /// 往指定的GroupBox中添加對象                      /// </summary>                        /// <param name="gbView"></param>                        /// <param name="lbl"></param>                       private void AddItemToGroupBox(GroupBox gbView,Label lbl)                       {                              gbView.Invoke(new Action(() =>                            {                                PictureBox p = new PictureBox();                               p.Width = 20;                                p.Height = 20;                               p.Dock = DockStyle.Left;                              p.Image = this.imgLst01.Images[0];                               p.Margin = new Padding(2);                               gbView.Controls.Add(p);                                           }));                             //顯示個數                            lbl.Invoke(new Action(() => {                               if (string.IsNullOrEmpty(lbl.Text))                                 {                                     lbl.Text = "0";                                }                                lbl.Text = (int.Parse(lbl.Text) + 1).ToString();                            }));                        }                     }                  }
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.