<strike id="suge2"></strike>
  • <tfoot id="suge2"></tfoot>
    <ul id="suge2"><sup id="suge2"></sup></ul>
    <ul id="suge2"><sup id="suge2"></sup></ul>
    <fieldset id="suge2"><input id="suge2"></input></fieldset>
    <ul id="suge2"><sup id="suge2"></sup></ul>
  • <ul id="suge2"></ul>

    南京軟件定制開發

    南京傾心軟件歡迎您訪問本站

    13605185909

    新聞資訊

    NEWS CENTER
    欄目導航

    南京軟件開發之AutoResetEvent使用介紹

    發布時間:Mar 23, 2021         已有 人瀏覽

    之前在博客園看到有位仁兄發表一篇關于AutoResetEvent介紹,看了下他寫的代碼,看上去沒什么問題,但仔細看還是能發現問題。下圖是這位仁兄代碼截圖。

    仁兄博客地址:http://www.cnblogs.com/lzjsky/archive/2011/07/11/2102794.html

    按照這種寫法自己試了下,運行起來并不是他這種結果(運行結果很隨機)。

    原因有以下兩點:

    1、支付線程與取書線程都屬于同級線程,運行先后順序是隨機的

    2、在循環內部調用AutoResetEvent.Set(),不能確定子線程是否按順序執行,有可能主線程已經循環多次,而子線程可能才循環一次

    修正

    首先,要明白實驗的場景。還是引用這位仁兄的例子:“我去書店買書,當我選中一本書后我會去收費處付錢,付好錢后再去倉庫取書。這個順序不能顛倒,我作為主線程,收費處和倉庫做兩個輔助線程” 。

    要實現上圖這種效果,得先確定好執行先后順序(上面已經說過):挑書-->收費-->取書-->完成

    代碼編寫如下:

    復制代碼
     1 class Program
     2     {
     3         static int _num = 0;
     4         //本例重點對象
     5         static AutoResetEvent _autoReset = new AutoResetEvent(false);
     6 
     7         static AutoResetEvent _autoReset0 = new AutoResetEvent(false);
     8         static AutoResetEvent _autoReset1 = new AutoResetEvent(false);
     9 
    10         //static AutoResetEvent autoReset2 = new AutoResetEvent(false);
    11         //static AutoResetEvent autoReset3 = new AutoResetEvent(false);
    12 
    13         //static object _payMoneyObj = new object();
    14         //static object _getBookObj = new object();
    15 
    16         private static void ThreadPayMoneyProc()
    17         {
    18             while (true)
    19             {
    20                 //_autoReset.WaitOne();
    21                 _autoReset0.WaitOne();
    22                 //lock (_payMoneyObj)
    23                 {
    24                     Console.WriteLine(Thread.CurrentThread.Name + ",編號: " + _num);
    25                     //通知主線程,錢已付完
    26                     //_autoReset2.Set();
    27                 }
    28             }
    29         }
    30 
    31         private static void TreadGetBookProc()
    32         {
    33             while (true)
    34             {
    35                 //_autoReset.WaitOne();
    36                 _autoReset1.WaitOne();
    37                 //lock (_getBookObj)
    38                 {
    39                     Console.WriteLine(Thread.CurrentThread.Name + ",編號: " + _num);
    40                     //通知主線程,書已取走
    41                     //_autoReset3.Set();
    42                 }
    43             }
    44         }
    45 
    46 
    47         static void Main(string[] args)
    48         {
    49             //本案例是通過AutoResetEvent來實現多線程同步
    50             //購買書數量
    51             const int num = 50;
    52 
    53             //付錢線程
    54             Thread threadPayMoney = new Thread(new ThreadStart(ThreadPayMoneyProc));
    55             threadPayMoney.Name = "付錢線程";
    56             //取書線程
    57             Thread threadGetBook = new Thread(new ThreadStart(TreadGetBookProc));
    58             threadGetBook.Name = "取書線程";
    59 
    60             //開始執行線程
    61             threadPayMoney.Start();
    62             threadGetBook.Start();
    63 
    64             //主線程開始選書
    65             Console.WriteLine("----------------主線程開始選書!------------------");
    66             for (int i = 1; i <= num; i++)
    67             {
    68                 Console.WriteLine("主線程選書編號:" + i);
    69                 _num = i;
    70                 //_autoReset.Set();
    71 
    72                 //通知付錢線程
    73                 _autoReset0.Set();
    74                 //主線延時1ms執行(但不知道付錢線程這個過程需要多少時間)
    75                 Thread.Sleep(1);
    76                 //_autoReset2.WaitOne();
    77 
    78                 //付完錢后,通知取書線程
    79                 _autoReset1.Set();
    80                 //主線延時1ms執行(但不知道取書線程這個過程需要多少時間)
    81                 Thread.Sleep(1);
    82                 //_autoReset3.WaitOne();
    83                 Console.WriteLine("-----------------------------------");
    84             }
    85 
    86             Console.ReadKey();
    87 
    88 
    89         }
    90     }
    復制代碼

    運行結果如下圖:

    這樣做,效果是出來了,但主線程不知道付費線程、取書線程執行需要多長時間。上例中給定的是1ms,但如果其中某個子線程超過了給定的休眠時間,主線會繼續往下執行,不會等待子線程處理完成。這樣就導致了買書編號與付錢和取書的編號不同步。也就混亂了。

    這時可以使用AutoResetEvent這個對象。上例中已經使用這個對象。沒錯,還可以在繼續使用。

    代碼如下圖:

    復制代碼
     1 class Program
     2     {
     3         static int _num = 0;
     4         //本例重點對象
     5         static AutoResetEvent _autoReset = new AutoResetEvent(false);
     6 
     7         static AutoResetEvent _autoReset0 = new AutoResetEvent(false);
     8         static AutoResetEvent _autoReset1 = new AutoResetEvent(false);
     9 
    10         static AutoResetEvent _autoReset2 = new AutoResetEvent(false);
    11         static AutoResetEvent _autoReset3 = new AutoResetEvent(false);
    12 
    13         //static object _payMoneyObj = new object();
    14         //static object _getBookObj = new object();
    15 
    16         private static void ThreadPayMoneyProc()
    17         {
    18             while (true)
    19             {
    20                 //_autoReset.WaitOne();
    21                 _autoReset0.WaitOne();
    22                 //lock (_payMoneyObj)
    23                 {
    24                     Console.WriteLine(Thread.CurrentThread.Name + ",編號: " + _num);
    25                     //通知主線程,錢已付完成
    26                     _autoReset2.Set();
    27                 }
    28             }
    29         }
    30 
    31         private static void TreadGetBookProc()
    32         {
    33             while (true)
    34             {
    35                 //_autoReset.WaitOne();
    36                 _autoReset1.WaitOne();
    37                 //lock (_getBookObj)
    38                 {
    39                     Console.WriteLine(Thread.CurrentThread.Name + ",編號: " + _num);
    40                     //通知主線程,書已取走
    41                     _autoReset3.Set();
    42                 }
    43             }
    44         }
    45 
    46 
    47         static void Main(string[] args)
    48         {
    49             //本案例是通過AutoResetEvent來實現多線程同步
    50             //購買書數量
    51             const int num = 5;
    52 
    53             //付錢線程
    54             Thread threadPayMoney = new Thread(new ThreadStart(ThreadPayMoneyProc));
    55             threadPayMoney.Name = "付錢線程";
    56             //取書線程
    57             Thread threadGetBook = new Thread(new ThreadStart(TreadGetBookProc));
    58             threadGetBook.Name = "取書線程";
    59 
    60             //開始執行線程
    61             threadPayMoney.Start();
    62             threadGetBook.Start();
    63 
    64             //主線程開始選書
    65             Console.WriteLine("----------------主線程開始選書!------------------");
    66             for (int i = 1; i <= num; i++)
    67             {
    68                 Console.WriteLine("主線程選書編號:" + i);
    69                 _num = i;
    70                 //_autoReset.Set();
    71 
    72                 //通知付錢線程
    73                 _autoReset0.Set();
    74                 //主線延時1ms執行(但不知道付錢線程這個過程需要多少時間)
    75                 //Thread.Sleep(1);
    76                 //等待付錢線程
    77                 _autoReset2.WaitOne();
    78 
    79                 //付完錢后,通知取書線程
    80                 _autoReset1.Set();
    81                 //主線延時1ms執行(但不知道取書線程這個過程需要多少時間)
    82                 //Thread.Sleep(1);
    83                 //等待取書線程
    84                 _autoReset3.WaitOne();
    85                 Console.WriteLine("-----------------------------------");
    86                 //完成后,繼續下一個任務處理
    87             }
    88 
    89             Console.ReadKey();
    90 
    91 
    92         }
    93     }
    復制代碼

    運行結果如下圖:

    運行結果和上面使用指定主線程休眠所運行結果是一樣的。但是,可以不用指定主線程休眠時間,也不需要指定。因為你沒法估計子線程所運行的時間,而且每次運行時間都不一樣。

    后話

    本例中, 買書場景其實有兩種編程結構(或者編程思想)。一種是本例中的,買書是主線程,而收銀臺(付錢線程)、倉庫(取書線程)。這兩個線程是一直存在的,一直跑著的。只要有書過來,這兩個線程就會執行。這可以聯系到現實中的收銀臺和倉庫。

    第二種編程思想,買書是一個發起線程,然后開啟一個付款線程和取書線程。這時,買書線程(主線程)可以確定這兩個子線程什么時候執行完成。使用 線程對象.Join(),執行完后,主線程接著下步任務處理。

    Copyright © 2020-2022 南京傾心軟件技術有限公司 版權所有     蘇ICP備2020070309號-1
    QQ在線咨詢
    13605185909
    返回頂部
    5555国产在线观看精品| 无码人妻精品一区二区三 | 国产69精品久久久久999三级| 午夜福利麻豆国产精品| 国产精品91在线| 亚洲欧洲精品在线| 99国产精品自在自在久久| 无码精品国产VA在线观看| 亚洲高清专区日韩精品 | 99re这里有免费视频精品| 国产办公室秘书无码精品99| 国产精品亚洲一区二区三区在线| 中文字幕在线精品| 久久青青草原精品国产不卡| 国产精品自在线拍国产第一页| 一级一级特黄女人精品毛片| 成人国产精品一区二区网站| 四虎精品亚洲一区二区三区| 亚洲国产婷婷综合在线精品| 国产精品JIZZ在线观看老狼| 国产精品自产拍在线观看花钱看 | 久久精品国产亚洲AV高清热 | 国产午夜久久精品| 国产在线麻豆精品观看| 国产91精品不卡在线| 中文字幕日韩亚洲| 日韩精品人妻系列无码专区| 亚洲区日韩精品中文字幕| 日韩亚洲人成在线综合| 四虎永久在线精品免费一区二区 | 99re热精品视频国产免费| 97精品国产91久久久久久久| 91精品免费高清在线| 精品日产卡一卡二卡麻豆| 国产精品99久久久久久人| 国产精品电影一区| 人人妻人人澡人人爽人人精品浪潮| 亚洲熟妇成人精品一区| 7777精品伊人久久久大香线蕉| 国产精品线在线精品| 日韩综合无码一区二区|