什麼是進程?html
當一個程序開始運行時,它就是一個進程,進程包括運行中的程序和程序所使用到的內存和系統資源。 而一個進程又是由多個線程所組成的。編程
什麼是線程?多線程
線程是程序中的一個執行流,每一個線程都有本身的專有寄存器(棧指針、程序計數器等),但代碼區是共享的,即不一樣的線程能夠執行一樣的函數。異步
什麼是多線程?函數
多線程是指程序中包含多個執行流,即在一個程序中能夠同時運行多個不一樣的線程來執行不一樣的任務,也就是說容許單個程序建立多個並行執行的線程來完成各自的任務。性能
前臺線程後臺線程?spa
應用程序的主線程和經過構造一個Thread對象來顯式建立的任何線程都默認是前臺線程。相反線程池線程默認爲後臺線程。另外由進入托管執行環境的本機代碼建立的任何線程都被標記爲後臺線程。操作系統
在線程的生命週期中,任什麼時候候均可以從前臺變爲後臺,或者從後臺變爲前臺。線程
前臺線程能阻止應用程序的終結。一直到全部的前臺線程終止後,CLR才能關閉應用程序(即卸載承載的應用程序域)。指針
後臺線程(有時也叫守護線程)被CLR認爲是程序執行中可作出犧牲的途徑,即在任什麼時候候(即便這個線程此時正在執行某項工做)均可能被忽略。所以,若是全部的前臺線程終止,當應用程序域卸載時,因此的後臺線程也會被自動終止。
線程是輕量級進程。一個使用線程的常見實例是現代操做系統中並行編程的實現。使用線程節省了 CPU 週期的浪費,同時提升了應用程序的效率。
線程生命週期開始於 System.Threading.Thread 類的對象被建立時,結束於線程被終止或完成執行時。
線程生命週期中的各類狀態:
未啓動狀態:當線程實例被建立但 Start 方法未被調用時的情況(將該線程標記爲能夠運行的狀態,但具體執行時間由cpu決定)。
就緒狀態:當線程準備好運行並等待 CPU 週期時的情況。
不可運行狀態:下面的幾種狀況下線程是不可運行的:(已經調用 Sleep 方法,已經調用 Wait 方法,經過 I/O 操做阻塞)
死亡狀態:當線程已完成執行或已停止時的情況。
一、主線程
進程中第一個被執行的線程稱爲主線程
輸出:This is MainThread
二、線程的建立
三、線程的管理
sleep()掛起和Abort() 銷燬線程
經過拋出 threadabortexception 在運行時停止線程。這個異常不能被捕獲,若是有 finally 塊,控制會被送至 finally 塊
線程掛起
using System; using System.Threading; namespace Threading { class Program { public static void Thread1() { Console.WriteLine("Thread1 starts"); Console.WriteLine("Thread1 Paused for 5 seconds"); Thread.Sleep(5000); Console.WriteLine("Thread1 resumes"); } static void Main(string[] args) { var t1 = new Thread(Thread1); t1.Start(); Console.ReadKey(); } } } 線程銷燬代碼 using System; using System.Threading; namespace Threading { class Program { public static void Thread1() { try { Console.WriteLine("Thread1 starts"); for (int i = 0; i <= 10; i++) { Thread.Sleep(500); Console.WriteLine(i); } Console.WriteLine("Thread1 Completed"); } catch (ThreadAbortException ex) { Console.WriteLine("Thread1 Abort Exception"); } finally { Console.WriteLine("Couldn't catch the Thread1 Exception"); } } static void Main(string[] args) { //開啓子線程 var t1 = new Thread(Thread1); t1.Start(); //主線程掛起2s Thread.Sleep(2000); //終止t1子線程 t1.Abort(); Console.ReadKey(); } } }
在多線程程序中,線程把大部分的時間花費在等待狀態,等待某個事件發生,而後才能給予響應咱們通常用ThreadPool(線程池)來解決;線程平時都處於休眠狀態,只是週期性地被喚醒咱們使用使用Timer(定時器)來解決。
因爲線程的建立和銷燬須要耗費必定的開銷,過多的使用線程會形成內存資源的浪費,出於對性能的考慮,因而引入了線程池的概念。線程池維護一個請求隊列,線程池的代碼從隊列提取任務,而後委派給線程池的一個線程執行,線程執行完不會被當即銷燬,這樣既能夠在後臺執行任務,又能夠減小線程建立和銷燬所帶來的開銷。線程池線程默認爲後臺線程。
線程池自動管理線程線程的建立和銷燬。
代碼展現:
using System; using System.Threading; namespace Threading { class Program { public static void Thread1(object data) { Console.WriteLine("Thread1 => {0}", data.ToString()); } static void Main(string[] args) { //控制線程數大小 //第一個參數是:線程池中輔助線程的最大數目 //第二個參數是:線程池中異步 I/O 線程的最大數目 ThreadPool.SetMaxThreads(3, 3); for (int i = 0; i < 10; i++) { //ThreadPool是靜態類無需實例化, //ThreadPool.QueueUserWorkItem(new WaitCallback(Thread1), i); ThreadPool.QueueUserWorkItem(Thread1, i); } Console.WriteLine("Thread1 sleep"); Thread.Sleep(100000); Console.WriteLine("Thread1 end"); Console.ReadKey(); } } }
其實,線程池的啓動和終止不是咱們程序所能控制的,線程池中的線程執行完以後是沒有返回值的,咱們能夠用ManualResetEvent通知一個或多個正在等待的線程已發生事件.
http://www.cnblogs.com/yinrq/p/5412238.html
ThreadPool:
https://msdn.microsoft.com/zh-cn/library/system.threading.threadpool.aspx#Y0
ManualResetEvent:
https://msdn.microsoft.com/zh-cn/library/system.threading.manualresetevent.aspx
多線程的好處:
能夠提升CPU的利用率。在多線程程序中,一個線程必須等待的時候,CPU能夠運行其它的線程而不是等待,這樣就大大提升了程序的效率。
多線程的不利方面:
線程也是程序,因此線程須要佔用內存,線程越多佔用內存也越多;
多線程須要協調和管理,因此須要CPU時間跟蹤線程;
線程之間對共享資源的訪問會相互影響,必須解決競用共享資源的問題;
線程太多會致使控制太複雜,最終可能形成不少Bug;