第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)
一. 并行編程
1. 區分串行編程和串行編程
①. 串行編程:所謂的串行編程就是單線程的作用下,按順序執行。(典型代表for循環 下面例子從1-100按順序執行)
②. 并行編程:充分利用多核cpu的優勢,同時開啟多個線程并行執行。(典型代表Parallel.For循環 下面例子從1-100無序執行)
?代碼實踐:
?
1 {2 //1. 串行 (從1-100按順序執行)3 for (int i = 1; i < 100; i++)4 {5 Console.WriteLine(i);6 }7 //2. 并行 (從1-100無序執行)8 Parallel.For(1, 100, (item) =>9 { 10 Console.WriteLine(item); 11 }); 12 }?
結論:串行的代碼按順序依次輸出,并行的代碼無順序輸出。
2. 深究Parallel類中的方法 (For方法、ForEach方法、Invoke方法 這三個方法都是用來開啟線程的)
(1). Invoke方法
a. 該方法的作用就是用來同時開啟多個線程的。
b. 該方法有兩個重載,主要涉及到兩個參數,用來配置最大并行數(即線程數)和一個可變的Action委托數組(詳見源碼)。
案例一: 開啟五個不同的線程調用五個方法
我們發現一個現象,主線程等著這五個子線程執行完畢后才執行,但是我們并沒有寫線程等待的代碼,所以我們可以總結:
①:并行計算,開啟多個線程后,不需要再開辟線程等待,直接是主線程完成后續操作。
②:而普通多線程執行后,需要單獨再開辟一個線程等待,然后主線程再執行。
?
?代碼實踐:
?
1 { 2 Parallel.Invoke(() => this.TestThread("bct1") 3 , () => this.TestThread("bct2") 4 , () => this.TestThread("bct3") 5 , () => this.TestThread("bct4") 6 , () => this.TestThread("bct5") 7 ); 8 }案例二: 指定最大并行數進行線程調用
我們發現,五個任務中的四個任務同時由不同線程開啟,當其中一個任務結束時,第五個任務開啟,并由剛結束的任務的線程來執行。
?
{//設置最大的線程并行數ParallelOptions p = new ParallelOptions();p.MaxDegreeOfParallelism = 4;Parallel.Invoke(p, () => this.TestThread("bct1"), () => this.TestThread("bct2"), () => this.TestThread("bct3"), () => this.TestThread("bct4"), () => this.TestThread("bct5"));}(2). For方法 (前兩個參數之間的差,代表任務的個數)
這里介紹一個簡單重載: public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body);
fromInclusive:開始索引(含).
toExclusive:結束索引(不含).
body:將為每個迭代調用一次的委托.
當然該方法中的其他重載中也有很豐富的功能,比如也可以配置最大線程數。
代碼實踐:
1 {2 //案例一:前兩個參數之間的差,就為并行計算線程的個數3 {4 Parallel.For(5, 10, t =>5 {6 //這里的t分別為:5,6,7,8,9 五個數7 string name = string.Format("bct{0}", t);8 this.TestThread(name);9 }); 10 } 11 //案例二: 配置最大并行數 12 //結果:同時最多5個線程執行,但是還是要執行9個任務,(6,7,8,9,10,11,12,13,14),后面四個任務等前面的執行完后,再執行 13 { 14 ParallelOptions po = new ParallelOptions() 15 { 16 MaxDegreeOfParallelism = 5 //表示最大線程數為5,后面即使配置超過5,也無效 17 }; 18 Parallel.For(6, 15, po, (t, state) => 19 { 20 string name = string.Format("bct{0}", t); 21 this.TestThread(name); 22 //state.Break(); //退出單次循環(沒看到實際作用) 23 // state.Stop(); //退出全部循環(沒看到實際作用) 24 //return; 25 }); 26 } 27 }?
(3). ForEach方法
這里也是介紹一個簡單的重載:int數組中的個數代表需要進行并行任務的個數,但并不一定所有任務同時執行,也不一定每個任務都是一個新線程執行。
該方法當然也可以配置最大并行數。
?代碼實踐:
?
{//數組里的個數,就為并行進行并行任務數Parallel.ForEach(new int[] { 3, 5, 44, 55, 100 }, t =>{//這里的t分別為:3, 5, 44, 55, 100五個數string name = string.Format("bct{0}", t);this.TestThread(name);} }?
?
二. 常見的編程模型
1.同步編程模型(SPM):單線線程、串行開發模式。
2.異步編程模型(APM):xxxbegin、xxxend的模式。
3.基于事件的編程模型(EAP): xxAsync這樣的事件模式。 eg:WebClient。
4.基于Task的編程模型(TAP): APM和EAP都可以使用Task來實現,微軟的初衷就是想通過Task大一統異步編程領域。
下面分享兩段代碼,不做深入研究了。
?
1 {2 FileStream fs = new FileStream(Environment.CurrentDirectory + "//1.txt", FileMode.Open);3 var bytes = new byte[fs.Length];4 var task = Task.Factory.FromAsync(fs.BeginRead, fs.EndRead, bytes, 0, bytes.Length, string.Empty);5 6 var nums = task.Result;7 8 Console.WriteLine(nums);9 } 10 { 11 FileStream fs = new FileStream(Environment.CurrentDirectory + "//1.txt", FileMode.Open); 12 13 var bytes = new byte[fs.Length]; 14 15 fs.BeginRead(bytes, 0, bytes.Length, (aysc) => 16 { 17 var nums = fs.EndRead(aysc); 18 19 Console.WriteLine(nums); 20 21 }, string.Empty); 22 23 Console.Read(); 24 }總結
以上是生活随笔為你收集整理的第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第九节:委托和事件(1)(委托的发展历史
- 下一篇: XHR简介