概論
多線程在構建大型系統的時候是需要重點關注的一個重要方面,特別是在效率(系統跑得多快?)和性能(系統工作正常?)之間做一個權衡的時候。恰當的使用多線程可以極大的提高系統性能。
什麼是線程?
每個正在系統上運行的程序都是一個進程。每個進程包含一到多個線程。進程也可能是整個程序或者是部分程序的動態執行。線程是一組指令的集合,或者是程序的特殊段,它可以在程序裡獨立執行。也可以把它理解為代碼運行的上下文。所以線程基本上是輕量級的進程,它負責在單個程序裡執行多任務。通常由操作系統負責多個線程的調度和執行。
在Win32環境中常用的一些模型。
·單線程模型
在這種線程模型中,一個進程中只能有一個線程,剩下的進程必須等待當前的線程執行完。這種模型的缺點在於系統完成一個很小的任務都必須占用很長的時間。
·塊線程模型(單線程多塊模型STA)
這種模型裡,一個程序裡可能會包含多個執行的線程。在這裡,每個線程被分為進程裡一個單獨的塊。每個進程可以含有多個塊,可以共享多個塊中的數據。程序規定了每個塊中線程的執行時間。所有的請求通過Windows消息隊列進行串行化,這樣保證了每個時刻只能訪問一個塊,因而只有一個單獨的進程可以在某一個時刻得到執行。這種模型比單線程模型的好處在於,可以響應同一時刻的多個用戶請求的任務而不只是單個用戶請求。但它的性能還不是很好,因為它使用了串行化的線程模型,任務是一個接一個得到執行的。(此模型相當於在多線程中在一個線程執行的過程中,另外的線程都處於掛起的狀態,直到此線程執行結束,後再開始另一個線程)
·多線程塊模型(自由線程塊模型)
多線程塊模型(MTA)在每個進程裡只有一個塊而不是多個塊。這單個塊控制著多個線程而不是單個線程。這裡不需要消息隊列,因為所有的線程都是相同的塊的一個部分,並且可以共享。這樣的程序比單線程模型和STA的執行速度都要塊,因為降低了系統的負載,因而可以優化來減少系統idle的時間。這些應用程序一般比較復雜,因為程序員必須提供線程同步以保證線程不會並發的請求相同的資源,因而導致競爭情況的發生。這裡有必要提供一個鎖機制。但是這樣也許會導致系統死鎖的發生。
多線程在.NET裡如何工作?
在本質上和結構來說,.NET是一個多線程的環境。有兩種主要的多線程方法是.NET所提倡的:使用ThreadStart來開始你自己的進程,直接的(使用ThreadPool.QueueUserWorkItem)或者間接的(比如Stream.BeginRead,或者調用BeginInvoke)使用ThreadPool類。一般來說,你可以"手動"為長時間運行的任務創建一個新的線程,另外對於短時間運行的任務尤其是經常需要開始的那些,進程池是一個非常好的選擇。進程池可以同時運行多個任務,還可以使用框架類。對於資源緊缺需要進行同步的情況來說,它可以限制某一時刻只允許一個線程訪問資源。這種情況可以視為給線程實現了鎖機制。線程的基類是System.Threading。所有線程通過CLI來進行管理。
如何使用線程
using System.Threading;
所有與多線程機制應用相關的類都是放在System.Threading命名空間中的.
Thread類用於創建線程.
ThreadPool類用於管理線程池等等.
如果你想在你的應用程序中使用多線程,就必須包含這個Thread類.
Thread類有幾個至關重要的方法:
Start():啟動線程.
Sleep(int):靜態方法,暫停當前線程指定的毫秒數.
Abort():通常使用該方法來終止一個線程.
Suspend():該方法並不終止未完成的線程,它僅僅掛起線程,以後還可恢復.
Resume():恢復被Suspend()方法掛起的線程的執行.
簡單線程示例
class Program
{
static void Main(string[] args)
{
ThreadStart threadStart = new ThreadStart(SayHello);
Thread thread = new Thread(threadStart);
thread.Start();
Thread.Sleep(5000);
}
public static void SayHello()
{
Console.Write("Spring Yang say hello to you.
hello,every one.");
}
}
運行結果:
傳遞單個參數
class Program
{
static void Main(string[] args)
{
string message = "Hello everyone.";
ParameterizedThreadStart threadStart = new ParameterizedThreadStart(SayHello);
Thread thread = new Thread(threadStart);
thread.Start(message);
Thread.Sleep(5000);
}
public static void SayHello(object message)
{
Console.Write("Spring Yang say hello to you.
{0}.",message);
}
}
結果:
傳遞多個參數:
class Program
{
static void Main(string[] args)
{
ThreadTest threadTest = new ThreadTest("spring yang", "How are you?");
ThreadStart threadStart = new ThreadStart(threadTest.SayHello);
Thread thread = new Thread(threadStart);
thread.Start();
Thread.Sleep(5000);
}
}
public class ThreadTest
{
private string _userName;
private string _message;
public string UserName
{
get { return _userName; }
set { _userName = value; }
}
public string Message
{
get { return _message; }
set { _message = value; }<