多線程學習筆記《-》

1.進程:是操做系統結構的基礎;是一個正在執行的程序;計算機中正在運行的程序實例;能夠分配給處理器並由處理器執行的一個實體;由單一順序的執行顯示,一個當前狀態和一組相關的系統資源所描述的活動單元。
2.線程:線程是程序中一個單一的順序控制流程。是程序執行流的最小單元。另外,線程是進程中的一個實體,是被系統獨立調度和分派的基本單位,線程本身不擁有系統資源,只擁有一點在運行中必不可少的資源,但它可與同屬一個進程的其它線程共享進程所擁有的所有資源。一個線程能夠建立和撤消另外一個線程,同一進程中的多個線程之間能夠併發執行。因爲線程之間的相互制約,導致線程在運行中呈現出間斷性。線程也有就緒、阻塞和運行三種基本狀態。每個程序都至少有一個線程,若程序只有一個線程,那就是程序自己。

3.多線程:在單個程序中同時運行多個線程完成不一樣的工做,稱爲多線程。
    web

小結:其實更容易理解一點進程與線程的話,能夠舉這樣一個例子:把進程理解成爲一個運營着的公司,然而每個公司員工就能夠叫作一個進程。每一個公司至少要有一個員工,員工越多,若是你的管理合理的話,公司的運營速度就會越好。這裏官味一點話就是說。cpu大部分時間處於空閒時間,浪費了cpu資源,多線程可讓一個程序「同時」處理多個事情,提升效率。
     多線程

單線程問題演示
     併發

建立一個WinForm應用程序,這裏出現的問題是,點擊按鈕後若是在彈出提示框以前,窗體是不能被拖動的。
函數

複製代碼ui

  1. private void button1_Click(object sender, EventArgs e)this

  2.         {spa

  3.             for (int i = 0; i < 10000000000; i++)  操作系統

  4.             {線程

  5.                 i += 1;orm

  6.             }

  7.             MessageBox.Show("出現後能拖動,提示沒出現以前窗體不能被拖動");

  8.         }


緣由:運行這個應用程序的時候,窗體應用程序自帶一個叫作UI的線程,這個線程負責窗體界面的移動大小等。若是點擊按鈕則這個線程就去處理這個循環計算,而放棄了其它操做,故而窗體拖動無響應。這就是單線程帶來的問題。
解決辦法:使用多線程,咱們本身建立線程。把計算代碼放入咱們本身寫的線程中,UI線程就能繼續作他的界面響應了。
    

線程的建立
    

線程的實現:線程必定是要執行一段代碼的,因此要產生一個線程,必須先爲該線程寫一個方法,這個方法中的代碼,就是該線程中要執行的代碼,然而啓動線程時,是經過委託調用該方法的。線程啓動是,調用傳過來的委託,委託就會執行相應的方法,從而實現線程執行方法。

複製代碼

  1. //建立線程  

  2.         private void button1_Click(object sender, EventArgs e)

  3.         {

  4.             //ThreadStart是一個無參無返回值的委託。

  5.             ThreadStart ts = new ThreadStart(js);

  6.             //初始化Thread的新實例,並經過構造方法將委託ts作爲參數賦初始值。

  7.             Thread td = new Thread(ts);   //須要引入System.Threading命名空間

  8.             //運行委託

  9.             td.Start();

  10.         }

  11.         //建立的線程要執行的函數。

  12.         void js()

  13.         {

  14.             for (int i = 0; i < 1000000000; i++)

  15.             {

  16.                 i += 1;

  17.             }

  18.             MessageBox.Show("提示出現先後窗體都能被拖動");

  19.         }


把這個計算寫入本身寫的線程中,就解決了單線程中的界面無反應缺陷。
    

小結:建立線程的4個步驟:1.編寫線程索要執行的方法。2.引用System.Threading命名空。3.實例化Thread類,並傳入一個指向線程所要運行方法的委託。4.調用Start()方法,將該線程標記爲能夠運行的狀態,但具體執行時間由cpu決定。
    

方法重入(多個線程執行一個方法)
    

因爲線程可與同屬一個進程的其它線程共享進程所擁有的所有資源。
因此多個線程同時執行一個方法的狀況是存在的,然而這裏不通過處理的話會出現一點問題,線程之間前後爭搶資源,導致數據計算結果錯亂。 

複製代碼

  1. public partial class 方法重入 : Form

  2.     {

  3.         public 方法重入()

  4.         {

  5.             InitializeComponent();

  6.  

  7.             //設置TextBox類的這個屬性是由於,開啓ui線程,

  8.             //微軟設置檢測不容許其它線程對ui線程的數據進行訪問,這裏咱們把檢測關閉,也就容許了其它線程對ui線程數據的訪問。

  9.             //若是檢測不設置爲False,則報錯。

  10.             TextBox.CheckForIllegalCrossThreadCalls = false;

  11.         }

  12.  

  13.         private void button1_Click(object sender, EventArgs e)

  14.         {

  15.             textBox1.Text = "0";

  16.             //開啓第一個線程,對js方法進行計算

  17.             ThreadStart ts = new ThreadStart(js);

  18.             Thread td = new Thread(ts);

  19.             td.Start();

  20.  

  21.             //開啓第二個線程,對js方法進行計算

  22.             ThreadStart ts1 = new ThreadStart(js);

  23.             Thread td1 = new Thread(ts1);

  24.             td1.Start();

  25.         }

  26.         //多線程要重入的方法。

  27.         void js()

  28.         {

  29.             int a = Convert.ToInt32(textBox1.Text);

  30.             for (int i = 0; i < 2000; i++)

  31.             {

  32.                 a++;

  33.                 textBox1.Text = a.ToString();

  34.             }

  35.         }

  36.     }



出錯現象:點擊按鈕後TextBox1中數據爲2000+或2000,若是你看到的數據一直是2000說明你的計算機cpu比較牛X,這樣的話你想看到不是2000的話,你能夠多點擊幾回試試,真不行的話,代碼中給TextBox1賦值爲0,換作在界面中給textBox1數值默認值爲0試試看。
出錯緣由:兩個進程同時計算這個方法,不相干擾應該每一個線程計算的結果都是2000的,可是這裏的結果輸出卻讓人之外,緣由是第一個兩個線程同時計算,並非同時開始計算,而是根據cpu決定的哪一個先開始,哪一個後開始,雖然相差時間很少,但後開始的就會取用先開始計算過的數據計算,這樣就會致使計算錯亂。
解決辦法:解決這個的一個簡單辦法解釋給方法加鎖,加鎖的意思就是第一個線程取用過這個資源完畢後,第二個線程再來取用此資源。造成排隊效果。
下面給方法加鎖。

複製代碼

  1. //多線程要重入的方法,這裏加鎖。

  2.         void js()

  3.         {

  4.             lock (this)

  5.             {

  6.                 int a = Convert.ToInt32(textBox1.Text);

  7.                 for (int i = 0; i < 2000; i++)

  8.                 {

  9.                     a++;

  10.                     textBox1.Text = a.ToString();

  11.                 }

  12.             }

  13.         }


給方法加過鎖後,線程一前一後取用資源,就能避免不可預計的錯亂結果,第一個線程計算爲2000,第二個線程計算就是從2000開始,這裏的結果就爲4000。
    

小結:多線程能夠同時運行,提升了cpu的效率,這裏的同時並非同時開始,同時結束,他們的開始是由cpu決定的,時間相差不大,但會有不可預計的計算錯亂,這裏要注意相似上面例子致使的方法重入問題。
    

前臺線程後臺線程
    

.Net的公用語言運行時能區分兩種不一樣類型的線程:前臺線程和後臺線程。這二者的區別就是:應用程序必須運行完全部的前臺線程才能夠退出;而對於後臺線程,應用程序則能夠不考慮其是否已經運行完畢而直接退出,全部的後臺線程在應用程序退出時都會自動結束。
問題:關閉了窗口,消息框還能彈出。

複製代碼

  1. private void button1_Click(object sender, EventArgs e)

  2.         {

  3.             //開啓一個線程,對js方法進行計算

  4.             ThreadStart ts2 = new ThreadStart(js);

  5.             Thread td2 = new Thread(ts2);            

  6.             td2.Start();

  7.  

  8.         }        

  9.         void js()

  10.         {

  11.             for (int i = 0; i < 2000000000; i++)  //若是看不出效果這裏的2後面多加0

  12.             {

  13.                 i++;

  14.             }

  15.             MessageBox.Show("關閉了窗口我仍是要出來的!");

  16.         }

緣由:.Net環境使用Thread創建線程,線程默認爲前臺線程。即線程屬性IsBackground=false,而前臺線程只要有一個在運行則應用程序不關閉,因此知道彈出消息框後應用程序纔算關閉。
解決辦法:在代碼中設置td2.IsBackground=true;

相關文章
相關標籤/搜索