<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
    返回頂部
    自拍偷在线精品自拍偷无码专区 | 2022国内精品免费福利视频| 国产精品午夜电影| 免费精品国产自产拍在| 久久精品国产亚洲av高清漫画| 国产精品美女久久久久久2018| 中文国产成人精品久久下载| 国产精品麻豆VA在线播放| 影院无码人妻精品一区二区| 日韩亚洲不卡在线视频中文字幕在线观看 | 高清国产一级精品毛片基地| 精品深夜AV无码一区二区老年| 91精品国产91久久久久久青草| 久久99视频精品| 亚洲AV永久无码精品| 久久精品免费一区二区三区| 法国性xxxx精品hd| 国产亚洲精品成人a v小说| 久久精品国产亚洲精品| 国产精品青草久久久久福利99| 亚洲精品无码你懂的网站| 亚洲第一永久AV网站久久精品男人的天堂AV | 天天视频国产精品| 日韩乱码在线观看| 日韩一区二区三区电影在线观看 | 欧洲精品久久久av无码电影| 久久精品国产亚洲av麻| 久久精品国产亚洲AV果冻传媒| 久久精品乱子伦免费| 少妇精品无码一区二区三区| 久热这里只有精品视频6| 久久99精品国产麻豆| 亚洲精品在线播放视频| 久久精品国产亚洲AV忘忧草18| 91探花国产综合在线精品| 色妞妞www精品视频| 久久夜色精品国产噜噜亚洲a| 亚洲精品无码av中文字幕| MM1313亚洲精品无码久久| 精品久久久久亚洲| 日韩亚洲国产二区|