在.net framework class library中,所有與多線程機(jī)制應(yīng)用相關(guān)的類都是放在System.Threading命名空間中的。其中提供Thread類用于創(chuàng)建線程,ThreadPool類用于管理線程池等等,此外還提供解決了線程執(zhí)行安排,死鎖,線程間通訊等實(shí)際問(wèn)題的機(jī)制。如果你想在你的應(yīng)用程序中使用多線程,就必須包含這個(gè)類。Thread類有幾個(gè)至關(guān)重要的方法,描述如下:
internal class Account { int balance; Random r = new Random(); internal Account(int initial) { balance = initial; }
internal int Withdraw(int amount) { if (balance < 0) { file://如果balance小于0則拋出異常 throw new Exception("Negative Balance"); } //下面的代碼保證在當(dāng)前線程修改balance的值完成之前 //不會(huì)有其他線程也執(zhí)行這段代碼來(lái)修改balance的值 //因此,balance的值是不可能小于0的 lock (this) { Console.WriteLine("Current Thread:"+Thread.CurrentThread.Name); file://如果沒(méi)有l(wèi)ock關(guān)鍵字的保護(hù),那么可能在執(zhí)行完if的條件判斷之后 file://另外一個(gè)線程卻執(zhí)行了balance=balance-amount修改了balance的值 file://而這個(gè)修改對(duì)這個(gè)線程是不可見的,所以可能導(dǎo)致這時(shí)if的條件已經(jīng)不成立了 file://但是,這個(gè)線程卻繼續(xù)執(zhí)行balance=balance-amount,所以導(dǎo)致balance可能小于0 if (balance >= amount) { Thread.Sleep(5); balance = balance - amount; return amount; } else { return 0; // transaction rejected } } } internal void DoTransactions() { for (int i = 0; i < 100; i++) Withdraw(r.Next(-50, 100)); } }
internal class Test { static internal Thread[] threads = new Thread[10]; public static void Main() { Account acc = new Account (0); for (int i = 0; i < 10; i++) { Thread t = new Thread(new ThreadStart(acc.DoTransactions)); threads[i] = t; } for (int i = 0; i < 10; i++) threads[i].Name=i.ToString(); for (int i = 0; i < 10; i++) threads[i].Start(); Console.ReadLine(); } }
public class MonitorSample { public static void Main(String[] args) { int result = 0; file://一個(gè)標(biāo)志位,如果是0表示程序沒(méi)有出錯(cuò),如果是1表明有錯(cuò)誤發(fā)生 Cell cell = new Cell( );
//下面使用cell初始化CellProd和CellCons兩個(gè)類,生產(chǎn)和消費(fèi)次數(shù)均為20次 CellProd prod = new CellProd(cell, 20); CellCons cons = new CellCons(cell, 20);
Thread producer = new Thread(new ThreadStart(prod.ThreadRun)); Thread consumer = new Thread(new ThreadStart(cons.ThreadRun)); //生產(chǎn)者線程和消費(fèi)者線程都已經(jīng)被創(chuàng)建,但是沒(méi)有開始執(zhí)行
using System; using System.Collections; using System.Threading;
//這是用來(lái)保存信息的數(shù)據(jù)結(jié)構(gòu),將作為參數(shù)被傳遞 public class SomeState { public int Cookie; public SomeState(int iCookie) { Cookie = iCookie; } }
public class Alpha { public Hashtable HashCount; public ManualResetEvent eventX; public static int iCount = 0; public static int iMaxCount = 0; public Alpha(int MaxCount) { HashCount = new Hashtable(MaxCount); iMaxCount = MaxCount; }
int iX = 2000; Thread.Sleep(iX); //Interlocked.Increment()操作是一個(gè)原子操作,具體請(qǐng)看下面說(shuō)明 Interlocked.Increment(ref iCount); if (iCount == iMaxCount) { Console.WriteLine(); Console.WriteLine("Setting eventX "); eventX.Set(); } } }
public class SimplePool { public static int Main(string[] args) { Console.WriteLine("Thread Pool Sample:"); bool W2K = false; int MaxCount = 10;//允許線程池中運(yùn)行最多10個(gè)線程 //新建ManualResetEvent對(duì)象并且初始化為無(wú)信號(hào)狀態(tài) ManualResetEvent eventX = new ManualResetEvent(false); Console.WriteLine("Queuing {0} items to Thread Pool", MaxCount); Alpha oAlpha = new Alpha(MaxCount); file://創(chuàng)建工作項(xiàng) //注意初始化oAlpha對(duì)象的eventX屬性 oAlpha.eventX = eventX; Console.WriteLine("Queue to Thread Pool 0"); try { file://將工作項(xiàng)裝入線程池 file://這里要用到Windows 2000以上版本才有的API,所以可能出現(xiàn)NotSupportException異常 ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta), new SomeState(0)); W2K = true; } catch (NotSupportedException) { Console.WriteLine("These API's may fail when called on a non-Windows 2000 system."); W2K = false; } if (W2K)//如果當(dāng)前系統(tǒng)支持ThreadPool的方法. { for (int iItem=1;iItem < MaxCount;iItem++) { //插入隊(duì)列元素 Console.WriteLine("Queue to Thread Pool {0}", iItem); ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),new SomeState(iItem)); } Console.WriteLine("Waiting for Thread Pool to drain"); file://等待事件的完成,即線程調(diào)用ManualResetEvent.Set()方法 eventX.WaitOne(Timeout.Infinite,true); file://WaitOne()方法使調(diào)用它的線程等待直到eventX.Set()方法被調(diào)用 Console.WriteLine("Thread Pool has been drained (Event fired)"); Console.WriteLine(); Console.WriteLine("Load across threads"); foreach(object o in oAlpha.HashCount.Keys) Console.WriteLine("{0} {1}", o, oAlpha.HashCount[o]); } Console.ReadLine(); return 0;
Thread Pool Sample: Queuing 10 items to Thread Pool Queue to Thread Pool 0 Queue to Thread Pool 1 ... ... Queue to Thread Pool 9 Waiting for Thread Pool to drain 98 0 : HashCount.Count==0, Thread.CurrentThread.GetHashCode()==98 100 1 : HashCount.Count==1, Thread.CurrentThread.GetHashCode()==100 98 2 : ... ... Setting eventX Thread Pool has been drained (Event fired) Load across threads 101 2 100 3 98 4 102 1