使用Task的一些知識最佳化了一下同事的多執行緒協作取消的一串程式碼
最近在看一個同事的程式碼,程式碼的本意是在main方法中開啟10個執行緒,用這10個執行緒來處理一批業務邏輯,在某一時刻當你命令console退出的時候,這個
時候不是立即讓console退出,而是需要等待10個執行緒把檢測狀態之後的業務邏輯執行完之後再退出,這樣做是有道理的,如果強行退出會有可能造成子執行緒的業
務資料損壞,沒毛病吧,業務邏輯大概就是這樣。
一:現實場景
由於真實場景的程式碼比較複雜和繁瑣,為了方便演示,我將同事所寫的程式碼抽象一下,類似下面這樣,看好了咯~~~
1 class Program 2 { 3 private static int workThreadNums = 0; 4 5 private static bool isStop = false; 6 7 static void Main(string[] args) 8 { 9 var tasks = new Task[10];10 11 12 for (int i = 0; i 15 {16 Run();17 }, i);18 }19 20 //是否退出21 string input = Console.ReadLine();22 23 while ("Y".Equals(input, StringComparison.OrdinalIgnoreCase))24 {25 break;26 }27 28 isStop = true;29 30 while (workThreadNums != 0)31 {32 Console.WriteLine("正在等待執行緒結束,當前還在執行執行緒有:{0}", workThreadNums);33 34 Thread.Sleep(10);35 }36 Console.WriteLine("準備退出了。。。");37 Console.Read();38 Environment.Exit(0);39 }40 41 static void Run()42 {43 try44 {45 workThreadNums++;46 47 while (true)48 {49 if (isStop) break;50 51 Thread.Sleep(1000);52 53 //執行業務邏輯54 Console.WriteLine("我是執行緒:{0},正在執行業務邏輯", Thread.CurrentThread.ManagedThreadId);55 }56 }57 finally58 {59 workThreadNums--;60 }61 }62 }
其實掃一下上面的程式碼應該就知道是用來幹嘛的,業務邏輯沒毛病,基本可以實現剛才的業務場景,在console退出的時候可以完全確保10個執行緒都把自己的業
務邏輯處理完畢了。不過從美觀角度上來看,這種程式碼就太low了。。。一點檔次都沒有,比如存在下面兩點問題:
第一點:區域性變數太多,又是isStop又是workThreaNums,導致業務邏輯Run方法中摻雜了很多的非業務邏輯,可讀性和維護性都比較low。
第二點:main函式在退出的時候用while檢測workThreadNums是否為“0”,貌似沒問題,但仔細想想這段程式碼有必要嗎?
接下來我把程式碼跑一下,可以看到這個while檢測到了在退出時的workThredNums的中間狀態“7”,有點意思吧~~~
二:程式碼最佳化
那上面這段程式碼怎麼最佳化呢?如何踢掉業務邏輯方法中的非業務程式碼呢?當然應該從業務邏輯上考慮一下了,其實這個問題的核心就是兩點:
1. 如何實現多執行緒中的協作取消?
2. 如何實現多執行緒整體執行完畢通知主執行緒?
這種場景最佳化千萬不要受到前人寫的程式碼所影響,最好忘掉就更好了,不然你會下意識的受到什麼workthreadnums,isstop這些變數的左右,不說廢話了,如
果你對task併發模型很熟悉的話,你的最佳化方案很快就會出來的。。。
1. 協作取消:
直接用一個bool變數來判斷子執行緒是否退出的辦法其實是很沒有檔次的,在net 4.0中有一個類(CancellationTokenSource)專門來解決使用bool變數來判
斷的這種很low的場景,而且比bool變數具有更強大的功能,這個會在以後的文章中跟大家去講。
2. 多執行緒整體執行完畢通知主執行緒
目前我們看到的方式是主執行緒透過輪詢workthreadnums這種沒有檔次的方式去做的,其實這種方式本質上就是任務序列,而如果你明白task的話,你就知道
有很多的手段是執行任務序列的,比如什麼ContinueWith,WhenAll,WhenAny等等方式,所以你只需要將一組task串聯到WhenAll之後就可以了。好了,上
面就是我的解決思路,接下來看一下程式碼吧:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 CancellationTokenSource source = new CancellationTokenSource(); 6 7 var tasks = new Task[10]; 8 9 for (int i = 0; i 12 {13 Run(source.Token);14 }, i);15 }16 17 Task.WhenAll(tasks).ContinueWith((t) =>18 {19 Console.WriteLine("準備退出了。。。");20 Console.Read();21 Environment.Exit(0);22 });23 24 string input = Console.ReadLine();25 while ("Y".Equals(input, StringComparison.OrdinalIgnoreCase))26 {27 source.Cancel();28 }29 30 Console.Read();31 }32 33 static void Run(CancellationToken token)34 {35 while (true)36 {37 if (token.IsCancellationRequested) break;38 39 Thread.Sleep(1000);40 41 //執行業務邏輯42 Console.WriteLine("我是執行緒:{0},正在執行業務邏輯", Thread.CurrentThread.ManagedThreadId);43 }44 }45 }
單從程式碼量上面看就縮減了17行程式碼,而且業務邏輯也非常的簡單明瞭,然後再看業務邏輯方法Run,其實你根本就不需要所謂的workThreadNums++,--
的操作,而且多執行緒下不用鎖的話,還容易出現競態的問題,解決方案就是使用WhenAll等待一組Tasks完成任務,之後再序列要退出的Task任務,是不是很完美,
而協作取消的話,只需將取消的token傳遞給業務邏輯方法,當主執行緒執行source.Cancel()方法取消的時候,子執行緒就會透過IsCancellationRequested感知到主
執行緒做了取消操作。
好了,就說這麼多吧,還是那句話,”因為我們視野的不開闊,導致缺乏解決問題的手段“,所以古話說得好,磨刀不誤砍柴工。。。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1727/viewspace-2806251/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用Task的一些知識優化了一下同事的多執行緒協作取消的一串程式碼優化執行緒
- 手撕Java多執行緒(四)執行緒之間的協作Java執行緒
- 多執行緒程式設計的基礎知識點執行緒程式設計
- 關於多執行緒協作的疑問執行緒
- 執行緒 、程式、協程的基本使用執行緒
- 執行緒(一)——執行緒,執行緒池,Task概念+程式碼實踐執行緒
- 多執行緒程式設計基礎知識執行緒程式設計
- 多執行緒系列(四):Task執行緒
- 多執行緒基礎知識執行緒
- .net使用Task多執行緒執行任務 .net限制執行緒數量執行緒
- Python——程式、執行緒、協程、多程式、多執行緒(個人向)Python執行緒
- 多執行緒程式是如何執行程式碼的?執行緒行程
- 執行緒間的協作機制執行緒
- Android小知識-Java多執行緒的基礎知識瞭解下AndroidJava執行緒
- 執行緒以及多執行緒,多程式的選擇執行緒
- Task+ConcurrentQueue多執行緒程式設計執行緒程式設計
- 多執行緒-程式和執行緒的概述執行緒
- Java多執行緒-執行緒池的使用Java執行緒
- Java多執行緒相關知識Java執行緒
- 多執行緒程式設計基礎(一)-- 執行緒的使用執行緒程式設計
- Android程式設計師必須掌握的知識點-多程式和多執行緒Android程式設計師執行緒
- 多執行緒-多執行緒方式1的程式碼實現執行緒
- 前置知識—程式和執行緒執行緒
- JAVA執行緒中的安全知識Java執行緒
- java多執行緒之執行緒的基本使用Java執行緒
- 多執行緒-執行緒組的概述和使用執行緒
- 多執行緒-執行緒池的概述和使用執行緒
- iOS多執行緒的使用iOS執行緒
- 多執行緒:barrier的使用執行緒
- 多執行緒程式設計基礎(二)-- 執行緒池的使用執行緒程式設計
- 執行緒和程式基礎以及多執行緒的基本使用(iOS)執行緒iOS
- 執行緒 執行緒池 Task執行緒
- C++知識點:對於多執行緒的總結C++執行緒
- 多執行緒基礎必要知識點!看了學習多執行緒事半功倍執行緒
- 執行緒間協作執行緒
- 多執行緒之初識執行緒執行緒
- 《面試補習》- 多執行緒知識梳理面試執行緒
- 多執行緒基礎知識點梳理執行緒