在論壇上見有人說有這麼個經典的面試題,我也來說說,^_^
此題涉及到:多線程,同步,排他
那前面順便講一下兩個排他應用的AutoResetEvent與ManualResetEvent的區別
AutoResetEvent:通知正在等待的線程已發生事件
ManualResetEvent :通知一個或多個正在等待的線程已發生事件
它們常用的三個事件有:
1)Set(); 2)ReSet(); 3)WaitOne();
字面上來說,一個是自動,一個是手動,其最跟本的區別是
一.AutoResetEvent的Set()只允許一個線程運行.也就是說AutoResetEvent的Set()方法,只會使一個線程得到運行,而使其它處於
WaitOne()狀態的線程自動爲ReSet()的無信號狀態.
二.而ManualResetEvent 的Set()則不會使處於WaitOne()狀態的線程自動爲ReSet()的無信號狀態.如果想其處於無信號狀態,必須手動調用ReSet()方法.
//-----------------------------------------------------------------------
下面就直接給代碼了
using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;
namespace ThreadTest
{
#region main
class Program
{
static void Main(string[] args)
{
TheadTest th = new TheadTest();
th.Start();
Console.ReadKey();
}
}
/// <summary>
/// 定義一個線程類
/// </summary>
class TheadTest
{
//定義一個Stream對象接收打開文件
private FileStream st;
//構造方法
public TheadTest()
{
}
public void Start()
{
//定義兩個信號鎖
AutoResetEvent ateA = new AutoResetEvent(false);
AutoResetEvent ateB = new AutoResetEvent(false);
//把信號鎖加入到List中
List<AutoResetEvent> lst = new List<AutoResetEvent>();
lst.Add(ateA);
lst.Add(ateB);
//定義帶參數的輸出偶數線程
Thread thrEven = new Thread(new ParameterizedThreadStart(OutPutEven));
//把兩個信號鎖傳入線程
thrEven.Start(lst);
//定義帶參數的輸出奇數線程
Thread thrOdd = new Thread(new ParameterizedThreadStart(OutPutOdd));
thrOdd.Start(lst);
}
private void OutPutEven(object lst)
{
AutoResetEvent ateA = (lst as List<AutoResetEvent>)[0];
AutoResetEvent ateB = (lst as List<AutoResetEvent>)[1];
for (int i = 0; i < 100; i += 2)
{
//設置本線程爲無信號
ateA.WaitOne();
//輸出
Console.WriteLine(i);
//st = File.Open(@"C:\file.txt", FileMode.Open); //用來測試同時訪問文件系統的
//st.Close();
ateB.Set(); //設置輸出奇數線程有信號
//Thread.Sleep(500);
}
}
private void OutPutOdd(object lst)
{
AutoResetEvent ateA = (lst as List<AutoResetEvent>)[0];
AutoResetEvent ateB = (lst as List<AutoResetEvent>)[1];
//設置偶數線程先輸出
ateA.Set();
for (int i = 1; i < 100; i += 2)
{
//設置本線程爲無信號
ateB.WaitOne();
Console.WriteLine(i);
//st = File.Open(@"C:\file.txt", FileMode.Open); //用來測試同時訪問文件系統的
//st.Close();
ateA.Set(); //設置輸出偶數線程有信號
//Thread.Sleep(500);
}
}
}
#endregion main
}