在上篇文章中我們使用了Wait和Pulse 實現了Countdown
接下來我們可以使用剛剛寫的Countdown 類來實現兩個線程的交會。
public static void MainThread()
{
Random r = new Random();
new Thread(Mate).Start(r.Next(1000));
Thread.Sleep(r.Next(10000)); //主線程睡眠一段時間
_countdown.Singnal(); //向_countdown注冊信號,告知主線程已經來了。
_countdown.Wait(); //等待其他線程
Console.WriteLine("Mate!");
}
static void Mate(object delay)
{
Thread.Sleep((int)delay);//線程睡眠。
_countdown.Singnal(); //向_countdown注冊信號,告知線程已經來了。
_countdown.Wait(); //等待其他線程。
Console.WriteLine("Mate!");
}
}
學生A早上睡覺,然后起床來到交會點,然后告訴老師,我來了,接著等待老師的出發命令,因為老師知道有兩個學生要去春游,所以現在只來了一個,還有一個沒有來,所以老師會讓學生A等待,阻塞。
學生B也是睡覺,接著也來到交會點,告訴老師,我也來了,然后等待老師的出發命令。
當學生B告訴老師我來了的時候,此時老師的剩余等待學生計數為0,所以老師告訴這兩個學生,你們可以出發了。
.net framework 4.0 提供了Barrier 的構造來實現線程交會的功能。如圖所示:
Thread1 調用SignalAndWait告知Barrier,我已經來了,然后阻塞。
Thread3調用SignalAndWait告知Barrier,我已經來了,然后阻塞。
Thread2 調用SignalAndWait告知Barrier,我已經來了,Barrier知道現在三個線程都來了,所以讓他們繼續并發執行。
Barrier的方法簡介:
AddParticipants:增加參與者,也就是增加春游的人數。
RemoveParticipant:減少參與者,可能某人肚子痛,不能參加春游了。
SignalAndWait :參與者已經來了,并等待其他參與者的到來。
下面是使用Barrier的示例:
public static void Main()
{
new Thread(Speak).Start();
new Thread(Speak).Start();
new Thread(Speak).Start();
}
static void Speak()
{
for (int i = 0; i < 5; i++)
{
Console.Write(i + " ");
_barrier.SignalAndWait(); //告知參與者已經來了,等待其他參與者
}
}
0 0 0 1 1 1 2 2 2 3 3 3 4 4 4
Barrier 的另一個非常有用的特性是在每一個階段完成的時候你都可以執行一個post-phase 的action委托。
什么是階段呢??,階段就是參與者全部都到了的時候。
如果我們修改Barrier的構造函數如下:
static Barrier _barrier = new Barrier(3, (barrier) => Console.WriteLine());
//說明有三個參與者,并且每次三個參與者完成任務的時候執行Console.WriteLine方法.
那么我們的輸出如下所示:
0 0 0
1 1 1
2 2 2
3 3 3
4 4 4
新聞熱點
疑難解答