C# 多线程经典示例 吃苹果

2017-01-10 08:18:59来源:cnblogs.com作者:飞翔的月亮人点击

本文主要讲述了多线程开发中经典示例,通过本示例,可以加深对多线程的理解。示例概述:  下面用一个模拟吃苹果的实例,说明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 代码如下:

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace DemoSharp.EatApple 8 { 9     /// <summary>10     /// 生产者11     /// </summary>12     public class Productor13     {14         private Dish dish;15         private string name;16 17         public string Name18         {19             get { return name; }20             set { name = value; }21         }22 23         public EventHandler PutAction;//声明一个事件,当放苹果时触发该事件24 25         public Productor(string name, Dish dish)26         {27             this.name = name;28             this.dish = dish;29         }30         public void run()31         {32             while (true)33             {34                 bool flag= dish.Put(name);35                 if (flag)36                 {37                     if (PutAction != null)38                     {39                         PutAction(this, null);40                     }41                     try42                     {43                         Thread.Sleep(600);//削苹果时间44                     }45                     catch (Exception ex)46                     {47 48                     }49                 }50                 else {51                     break;52                 }53             }54         }55     }56 }

Consumer代码如下:

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace DemoSharp.EatApple 8 { 9     /// <summary>10     /// 消费者11     /// </summary>12     public class Consumer13     {14         private string name;15 16         public string Name17         {18             get { return name; }19             set { name = value; }20         }21         private Dish dish;22         private int timelong;23 24         public EventHandler GetAction;//声明一个事件,当放苹果时触发该事件25 26         public Consumer(string name, Dish dish, int timelong)27         {28             this.name = name;29             this.dish = dish;30             this.timelong = timelong;31         }32         public void run()33         {34             while (true)35             {36                 bool flag=  dish.Get(name);37                 if (flag)38                 {39                     //如果取到苹果,则调用事件,并开始吃40                     if (GetAction != null)41                     {42                         GetAction(this, null);43                     }44                     try45                     {46                         Thread.Sleep(timelong);//吃苹果时间47                     }48                     catch (ThreadInterruptedException)49                     {50                     }51                 }52                 else {53                     break;54                 }55             }56         }57     }58 }

Dish代码如下:

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace DemoSharp.EatApple 8 { 9     /// <summary>10     /// 盘子,属于中间类11     /// </summary>12     public class Dish13     {14         private int f = 5;//表示盘子中还可以放几个苹果,最多只能放5个苹果15 16         private int EnabledNum;//可放苹果总数17 18         private int n = 0; //表示已经放了多少个苹果19 20         private object objGet = new object();21 22         private object objPut = new object();23 24         /// <summary>25         /// 构造函数,初始化Dish对象26         /// </summary>27         /// <param name="num">表示削够多少个苹果结束</param>28         public Dish(int num)29         {30             this.EnabledNum = num;31         }32         /// <summary>33         /// 放苹果的方法34         /// </summary>35         /// <param name="name"></param>36         ///<returns>是否放成功</returns>37         public bool Put(string name)38         {39             lock (this)//同步控制放苹果40             {41                 bool flag = false;42                43                 while (f == 0)//苹果已满,线程等待44                 {45                     try46                     {47                         System.Console.WriteLine(name + "正在等待放入苹果");48                         Monitor.Wait(this);49                     }50                     catch (Exception ex)51                     {52                         System.Console.WriteLine(name + "等不及了");53                     }54                 } 55                 if (n < EnabledNum)56                 {57                     f = f - 1;//削完一个苹果放一次58                     n = n + 1;59                     System.Console.WriteLine(name + "放1个苹果");60                     flag = true;61                 }62                 Monitor.PulseAll(this);63                 return flag;64             }65         }66 67         /// <summary>68         /// 取苹果的方法69         /// </summary>70         /// <param name="name"></param>71         public bool Get(string name)72         {73             lock (this)//同步控制取苹果74             {75                 bool flag = false;76                 while (f == 5)77                 {78                     try79                     {80                         System.Console.WriteLine(name + "等待取苹果");81                         Monitor.Wait(this);82                     }83                     catch (ThreadInterruptedException) { }84                 }85                 if (n <= EnabledNum)86                 {87                     f = f + 1;88                     System.Console.WriteLine(name + "取苹果吃...");89                     flag = true;90                 }91                 Monitor.PulseAll(this);92                 return flag;93             }94 95         }96     } 97 }

EatAppleSmp代码如下:

 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6  7 namespace DemoSharp.EatApple 8 { 9     public class EatAppleSmp10     {11         public EventHandler PutAction;//声明一个事件,当放苹果时触发该事件12 13         public EventHandler GetAction;//声明一个事件,当放苹果时触发该事件14 15         /// <summary>16         /// 开始吃苹果17         /// </summary>18         public void BeginEat()19         {20             Thread th_mother, th_father, th_young, th_middle, th_old;//依次表示妈妈,爸爸,小弟,二弟,大哥21             Dish dish = new Dish(30);22             Productor mother = new Productor("Mama", dish);//建立线程23             mother.PutAction += PutActionMethod;24             Productor father = new Productor("Baba", dish);25             father.PutAction += PutActionMethod;26             Consumer old = new Consumer("Dage", dish, 1200);27             old.GetAction += GetActionMethod;28             Consumer middle = new Consumer("Erdi", dish, 1500);29             middle.GetAction += GetActionMethod;30             Consumer young = new Consumer("Sandi", dish, 1800);31             young.GetAction += GetActionMethod;32             th_mother = new Thread(new ThreadStart(mother.run));33             th_mother.Name = "Mama";34             th_father = new Thread(new ThreadStart(father.run));35             th_father.Name = "Baba";36             th_old = new Thread(new ThreadStart(old.run));37             th_old.Name = "Dage";38             th_middle = new Thread(new ThreadStart(middle.run));39             th_middle.Name = "Erdi";40             th_young = new Thread(new ThreadStart(young.run));41             th_young.Name = "Sandi";42             th_mother.Priority = ThreadPriority.Highest;//设置优先级43             th_father.Priority = ThreadPriority.Normal;44             th_old.Priority = ThreadPriority.Lowest;45             th_middle.Priority = ThreadPriority.Normal;46             th_young.Priority = ThreadPriority.Highest;47             th_mother.Start();48             th_father.Start();49             th_old.Start();50             th_middle.Start();51             th_young.Start();52         }53 54         private void GetActionMethod(object sender,EventArgs e)55         {56             if (GetAction != null)57             {58                 GetAction(sender, e);59             }60         }61 62         private void PutActionMethod(object sender, EventArgs e)63         {64             if (PutAction != null)65             {66                 PutAction(sender, e);67             }68         }69     }70 }

界面类代码如下:

  1 using System;  2 using System.Collections.Generic;  3 using System.ComponentModel;  4 using System.Data;  5 using System.Drawing;  6 using System.Linq;  7 using System.Text;  8 using System.Windows.Forms;  9 using DemoSharp.EatApple; 10  11 namespace DemoSharp 12 { 13     /// <summary> 14     /// 页面类 15     /// </summary> 16     public partial class EatAppleForm : Form 17     { 18         private EatAppleSmp m_EatAppleSmp = new EatAppleSmp(); 19  20         public EatAppleForm() 21         { 22             InitializeComponent(); 23             InitView(); 24             m_EatAppleSmp.PutAction += PutActionMethod; 25             m_EatAppleSmp.GetAction += GetActionMethod; 26         } 27  28         /// <summary> 29         /// 初始化GroupBox 30         /// </summary> 31         private void InitView() 32         { 33             this.gbBaba.Controls.Clear(); 34             this.gbMama.Controls.Clear(); 35             this.gbDage.Controls.Clear(); 36             this.gbErdi.Controls.Clear(); 37             this.gbSandi.Controls.Clear(); 38         } 39  40         /// <summary> 41         /// 启动线程 42         /// </summary> 43         /// <param name="sender"></param> 44         /// <param name="e"></param> 45         private void btnStart_Click(object sender, EventArgs e) 46         { 47             this.m_EatAppleSmp.BeginEat(); 48         } 49  50         /// <summary> 51         /// 放苹果事件 52         /// </summary> 53         /// <param name="sender"></param> 54         /// <param name="e"></param> 55         private void PutActionMethod(object sender, EventArgs e) 56         { 57             Productor p = sender as Productor; 58             if (p != null) 59             { 60                 if (p.Name == "Baba") 61                 { 62                     AddItemToGroupBox(this.gbBaba, this.lblBaba); 63                 } 64                 if (p.Name == "Mama") 65                 { 66                     AddItemToGroupBox(this.gbMama, this.lblMama); 67                 } 68             } 69         } 70  71         /// <summary> 72         /// 吃苹果事件 73         /// </summary> 74         /// <param name="sender"></param> 75         /// <param name="e"></param> 76         public void GetActionMethod(object sender, EventArgs e) 77         { 78             Consumer c = sender as Consumer; 79             if (c != null) 80             { 81                 if (c.Name == "Dage") 82                 { 83                     AddItemToGroupBox(this.gbDage, this.lblDage); 84                 } 85                 if (c.Name == "Erdi") 86                 { 87                     AddItemToGroupBox(this.gbErdi, this.lblErdi); 88                 } 89                 if (c.Name == "Sandi") 90                 { 91                     AddItemToGroupBox(this.gbSandi, this.lblSandi); 92                 } 93             } 94         } 95  96         /// <summary> 97         /// 往指定的GroupBox中添加对象 98         /// </summary> 99         /// <param name="gbView"></param>100         /// <param name="lbl"></param>101         private void AddItemToGroupBox(GroupBox gbView,Label lbl)102         {103             gbView.Invoke(new Action(() =>104             {105                 PictureBox p = new PictureBox();106                 p.Width = 20;107                 p.Height = 20;108                 p.Dock = DockStyle.Left;109                 p.Image = this.imgLst01.Images[0];110                 p.Margin = new Padding(2);111                 gbView.Controls.Add(p);112 113             }));114             //显示个数115             lbl.Invoke(new Action(() => {116                 if (string.IsNullOrEmpty(lbl.Text))117                 {118                     lbl.Text = "0";119                 }120                 lbl.Text = (int.Parse(lbl.Text) + 1).ToString();121             }));122         }123     }124 }

 

 

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台