下面定義生產者CellProd和消費者類CellCons,它們都只有一個方法ThreadRun(),以便在Main()函數中提供給線程的ThreadStart代理對象,作為線程的入口。
public class CellProd
{
Cell cell; // 被操作的Cell對象
int quantity = 1; // 生產者生產次數,初始化為1
public CellProd(Cell box, int request)
{
//構造函數
cell = box;
quantity = request;
}
public void ThreadRun( )
{
for(int looper=1; looper<=quantity; looper++)
cell.WriteToCell(looper); file://生產者向操作對象寫入信息
}
}
public class CellCons
{
Cell cell;
int quantity = 1;
public CellCons(Cell box, int request)
{
cell = box;
quantity = request;
}
public void ThreadRun( )
{
int valReturned;
for(int looper=1; looper<=quantity; looper++)
valReturned=cell.ReadFromCell( );//消費者從操作對象中讀取信息
}
}
然後在下面這個類MonitorSample的Main()函數中我們要做的就是創建兩個線程分別作為生產者和消費者,使用CellProd.ThreadRun()方法和CellCons.ThreadRun()方法對同一個Cell對象進行操作。
public class MonitorSample
{
public static void Main(String[] args)
{
int result = 0; file://一個標志位,如果是0表示程序沒有出錯,如果是1表明有錯誤發生
Cell cell = new Cell( );
//下面使用cell初始化CellProd和CellCons兩個類,生產和消費次數均為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));
//生產者線程和消費者線程都已經被創建,但是沒有開始執行
try
{
producer.Start( );
consumer.Start( );
producer.Join( );
consumer.Join( );
Console.ReadLine();
}
catch (ThreadStateException e)
{
file://當線程因為所處狀態的原因而不能執行被請求的操作
Console.WriteLine(e);
result = 1;
}
catch (ThreadInterruptedException e)
{
file://當線程在等待狀態的時候中止
Console.WriteLine(e);
result = 1;
}
//盡管Main()函數沒有返回值,但下面這條語句可以向父進程返回執行結果
Environment.ExitCode = result;
}
}
大家可以看到,在上面的例程中,同步是通過等待Monitor.Pulse()來完成的。首先生產者生產了一個值,而同一時刻消費者處於等待狀態,直到收到生產者的“脈沖(Pulse)”通知它生產已經完成,此後消費者進入消費狀態,而生產者開始等待消費者完成操作後將調用Monitor.Pulese()發出的“脈沖”。它的執行結果很簡單:
Produce: 1
Consume: 1
Produce: 2
Consume: 2
Produce: 3
Consume: 3
...
...
Produce: 20
Consume: 20
事實上,這個簡單的例子已經幫助我們解決了多線程應用程序中可能出現的大問題,只要領悟了解決線程間沖突的基本方法,很容易把它應用到比較復雜的程序中去。