文章出處

線程基礎

一個進程由若干個線程組成,線程是程序執行的基本原子單位。線程是"進程"中某個單一順序的控制流,線程是進程中的一個基本執行流,每個線程都有自己專屬的寄存器(程序計數器、棧指針等),代碼共享區,不同的線程可以執行同樣的方法。

    多線程可以實現并行處理,可以避免某項任務長時間占用CPU時間,需要注意的是,多線程程序對于效率,應該根據任務不同的要求來選擇。

線程的命名空間System.Threading

    Thread類是線程中最重要的一個,Thread類提供了創建并控制線程,設置其優先級并獲取其狀態的方法。

    Thread類的聲明:

class ThreadSimple

{

//靜態線程函數

public static void ThreadMethodExample()

{

}

}

//調用靜態方法

Thread threadSimple = new Thread(ThreadSimple.ThreadMethodExample);

或:

class ThreadSimple

{

//靜態線程函數

public static void ThreadMethodExample()

{

}

//調用靜態方法

//Thread threadSimple = new Thread(ThreadSimple.ThreadMethodExample);

Thread threadSimple = new Thread(new ThreadStart(ThreadMethodExample));

}

  1. 線程啟動、結束

    Thread類的常用方法:

    1. IsAlive:判斷線程是否處于活動狀態
    2. Name:線程的名稱
    3. Priority:ThreadPriority枚舉類型,代表線程的優先級{Normal,AboveNormal,BelowNormal,Highest,Lowest}
    4. ThreadState:ThreadState枚舉類型,代表線程的狀態 { Running(線程已啟動,正在執行) , StopRequested(正在請求停止此線程), SuspendRequested(正在請求掛起此線程), Background(線程正在被作為后臺線程執行), Unstarted(尚未啟動線程),Stopped(線程已經停止),WaitSleepJoin(線程已經被阻止),Suspended(線程已經掛起),AbortRequested(對線程調用了Thread.Abort()方法但是線程尚未收到試圖終止它的掛起的System.Threading.ThreadAbortException) , Aborted(線程狀態包括AbortRequested,并且該線程現在已死,但其狀態尚未更改為Stopped) }
    5. Start:啟動一個線程
    6. Suspend:掛起一個線程的運行(暫停、中斷)
    7. Resume:繼續被掛起的線程,恢復被Suspend()方法掛起的線程的執行
    8. Abort():結束一個線程的運行,終止線程
    9. Sleep():線程的休眠,使線程進入一定時間的休眠狀態,時間一到,線程繼續執行
  2. 線程間數據同步
    1. 線程間數據共享

      多線程編程中,如果線程間需要共享數據,需要把共享的數據設置為靜態類型的,此時可以使用static關鍵字

    2. Lock語句同步數據訪問

      線程之間的同步和通信處理,兩個線程需要同時操作一個隊列,一個線程進行添加操作,另一個線程進行取用元素操作。

      lock關鍵字將語句塊標記為臨界區,方法是獲取給定對象的互斥鎖,執行語句,然后釋放該鎖。Lock的語法:lock(expression)statement_block【其中expression是加鎖對象,必須是引用類型,不能是數值類型,statement_block代表正在訪問的共享資源的程序段】,

      lock語句可以很好地實現互斥操作,從而保護數據在某個時刻內只有一個線程可以操作該數據,直至操作完成才允許其他線程進行操作,這樣就實現了按順序操作的設計,從而避免不可預料的情況發生。

public static void MethodSubB()

{

do

{

lock(lockExample)

{

i-=1;

Console.WriteLine("線程2開始,共享數據為:i={0}",i);

Thread.Sleep(2000); //線程A休眠2秒

Console.WriteLine("線程2結束,共享數據值i={0}",i);

}

} while (true);

}

    3.Mutex類同步數據訪問
    只向某個線程授予對共享資源的獨占訪問權,如果一個獲取了互斥體,那么想要獲取該互斥體的其他線程將被掛起,直到這個線程釋放該互                 斥體。

    線程可以使用Mutex.WaitOne()方法釋放這個對象,而在此期間,其他想要獲取這個Mutex對象的線程都只能等待。

 

    4.Monitor類同步數據訪問數

Monitor類用于鎖定對象,一個線程只有得到這把鎖才能對該對象進行操作,對象鎖保證了在可能引起混亂的情況下,一個時刻只有一個線程可以訪問這個對象。

Monitor必須和一個具體的對象相關聯,但由于它是一個靜態類,所以不能使用它來定義對象,而且它的所有方法都是靜態的,不能使用對象來引用。

當一個線程調用Monitor.Enter()方法鎖定對象時,這個對象就歸它所有了,其他線程想要訪問這個對象,只有等待它調用Monitor.Exit()方法釋放鎖。

            Monitor類主要成員

 

Enter

在指定對象上獲取排他鎖

Exit

釋放指定對象上的排它鎖

Pluse

通知等待隊列中的線程鎖定對象狀態的更改

PluseAll

通知所有的等待線程對象狀態的更改

TryEnter

試圖獲取指定對象上的排他鎖

Wait

釋放對象上的鎖并阻止當前線程,直到它重新獲取該鎖

 

private static Object sObjectA = new Object();

private static Object sObjectB = new Object();

public static void DemoA()

{

if(Monitor.TryEnter(sObjectA,1000))

{

Thread.Sleep(1000);

if (Monitor.TryEnter(sObjectB, 2000))

{

Monitor.Exit(sObjectB);

}

else

{

Console.WriteLine("TryEnter SObjectB超時...");

}

Monitor.Exit(sObjectA);

}

Console.WriteLine("執行DemoA");

}

public static void DemoB()

{

if (Monitor.TryEnter(sObjectB, 1000))

{

Thread.Sleep(1000);

if (Monitor.TryEnter(sObjectA, 2000))

{

Monitor.Exit(sObjectA);

}

else

{

Console.WriteLine("TryEnter SObjectA超時...");

}

Monitor.Exit(sObjectB);

}

Console.WriteLine("執行DemoB");

}

static void Main(string[] args)

{

Thread threadA = new Thread(DemoA);

Thread threadB = new Thread(DemoB);

threadA.Start();

threadB.Start();

Thread.Sleep(4000);

Console.WriteLine("線程結束");

}

 

    5.帶參數線程

    在不傳遞參數的情況下,可以使用ThreadStart代理來執行函數,如果要傳遞參數給執行函數,則可使用ParameterizedThreadStart代理來鏈接函數

    Thread類的4個重載的構造函數

 

      1.Thread(ThreadStart)[初始化Thread類的新實例]

      2.Thread(ParameterizedThreadStart)

      [初始化Thread類的新實例,指定允許對象在線程啟動時傳遞給線程的委托]

      3.Thread(ParameterizedThreadStart,Int32)

      4.Thread(ThreadStart,Int32)

      [初始化Thread類的新實例,并指定線程的最大堆棧]

實例:

class ThreadDemo

{

public int paraA, paraB;

public void MethodDemo()

{

Console.WriteLine("paraA={0},paraB={1}", paraA, paraB);

}

public void Print(object obj)

{

Console.WriteLine("傳入的參數是{0}", obj.ToString());

}

}

static void Main(string[] args)

{

ThreadDemo A = new ThreadDemo();

A.paraA = 2;

A.paraB = 3;

Thread threadA = new Thread(new ThreadStart(A.MethodDemo));

threadA.Start();

Thread threadB = new Thread(new ParameterizedThreadStart(new ThreadDemo().Print));

threadB.Start(" 這是傳入的參數");

 

 

Console.Write("Press any key to continue...");

Console.ReadKey();

}

 

  6.線程池ThreadPool

線程池是可以在后臺執行多個任務的線程集合,這使得主線程可以自由地異步執行其他任務。一旦池中的某個線程任務完成,它將返回到等待線程隊列中等待在此被使用。線程池線程都是后臺線程。

以下情況應該使用單獨的線程不宜使用線程池

1.線程需要指定優先級

2.線程執行的時間較長

3.線程在單獨的線程apartment中

4.在線程執行的過程中對線程存在操作

static void MethodA(object num)

{

int QueueNum = (int)num;

Console.WriteLine("線程號:{0}", QueueNum);

//輸出空行,為了美觀

Console.WriteLine();

}

static void Main(string[] args)

{

for (int i = 0; i < 5; i++)

{

//在線程池中創建線程池線程來執行指定的方法(用WaitCallBack來表示),并將此線程排入線程池的隊列等待執行

ThreadPool.QueueUserWorkItem(new WaitCallback(MethodA), i);

}

}


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()