多執行緒系列(二):多執行緒基礎

K戰神發表於2015-07-08

 

目錄

  • 執行緒的幾種狀態
  • 基礎執行緒
  • 前臺執行緒、後臺執行緒

一、執行緒的幾種狀態

 我們所說的基礎執行緒就是通過Thread類顯示建立的執行緒。可以大體瞭解一下Thread類相關的成員:

屬性:

方法:

 

執行緒的5個狀態:

1、建立狀態(new): 對應 Thread th= new Thread(worker) 時 ,就建立了一個新的執行緒,僅僅是新建狀態,程式還沒有執行執行緒中的程式碼~

 

2、就緒狀態(Runnable):  對應 th.Start()方法,新建執行緒在接收到Start()命令之後,呼叫Run()方法,具體的執行執行緒。

     * 雖然呼叫了Start()方法,但是執行緒也不一定即時執行Run()方法。我們知道,多執行緒是CPU線上程之間來回切換,給出一種多執行緒的感覺。

      如果資源緊張,執行緒較多,有可能在切換到當前這個執行緒前,需要等待一段時間。當CPU切換到當前這個執行緒時,在給定的時間片內執行我們的執行緒。

 

3、執行狀態(Running):  在切換到當前執行緒時,在CPU給定的時間片內,真正的執行執行緒。

 

4、  阻塞狀態(Blocked):  對應 Join()、Sleep()方法。阻塞狀態是當前執行執行緒,暫時中斷執行,讓出CUP時間片,使得其他正在等待Run()的執行緒可以真正Run()。

  <1> Join()方法:將呼叫Join()方法的執行緒,加入到當前執行緒。使得當前執行緒掛起,一直到呼叫Join()方法執行緒執行完畢。 

static void Main(string[] args)
{
            System.Threading.Thread childThead = new System.Threading.Thread(ChildThread);

            childThead.Start();

            //childThead.Join();

            Console.WriteLine("Main thread is end");


            Console.ReadKey();
        }

        static void ChildThread()
        {
            System.Threading.Thread.Sleep(10000);
            Console.WriteLine("ChildThread is end");
}

先顯示主執行緒的資訊,大約10s後,子執行緒資訊顯示,執行結果:

我們解開註釋:childThead.Join();  這裡需要理解的是,是將子執行緒childThead加入到主執行緒中,主執行緒掛起,直到子執行緒childThread執行完畢後,主執行緒才被喚醒,繼續執行。

我們想讓誰優先執行,就讓我們希望的執行緒呼叫Join().所以以上執行的結果是,首先顯示子執行緒資訊,完畢後,主執行緒才顯示資訊。

<2>Sleep()方法:使得當前執行緒休眠掛起相應的毫秒數,到了一定的時間就會喚醒自己,繼續執行。這裡休眠的毫秒數不一定是經過這個時間點就馬上喚醒,因為CPU需要線上程間來回切換。

  Thread.Sleep(0);在我們遇到長時間執行的執行緒時,執行一下,會讓CPU根據優先順序對執行緒重新排隊選擇。也許會是當前這個執行緒,或許是優先順序更高的。

<3>Suspend()這個方法不建議使用。

 

5、   死亡狀態(Dead): 對應 Abort()方法。讓執行緒進入死亡狀態有兩種方式:<1>程式結束後,執行緒自然就會結束。<2>執行中,丟擲異常。

   Abort(),就是讓執行緒丟擲異常來終止執行緒。 

 

二、基礎執行緒

1、建立執行緒

常用有2種方式可以讓我們顯示建立一個執行緒

public Thread(ThreadStart start);
public Thread(ParameterizedThreadStart start);

引數:ThreadStart(無參無返回值委託) 和 ParameterizedThreadStart(有一個引數無返回值委託)  就是一個委託,如下:

public delegate void ThreadStart();
public delegate void ParameterizedThreadStart(object obj);

先建立一個與之(此例為:ThreadStart委託)對應的方法:

static void ChildThread()
{
            System.Threading.Thread.Sleep(10000);
            Console.WriteLine("ChildThread is end");
}

再建立基礎執行緒:

System.Threading.Thread childThead = new System.Threading.Thread(ChildThread);

childThead.Start();

 

三、前臺執行緒與後臺執行緒

CLR將執行緒分為兩種,即前臺執行緒和後臺執行緒。

執行緒的狀態可以從前臺和後臺,在生命週期中來回切換。

應用程式主執行緒以及通過Thread物件顯示建立的執行緒預設為前臺執行緒,執行緒池的執行緒預設為後執行緒。

例項:

System.Threading.Thread backgroundThread = new System.Threading.Thread(BackGroundThreadWorker);

            if (!backgroundThread.IsBackground)
                backgroundThread.IsBackground = true;

            backgroundThread.Start();           

            var mt = System.Threading.Thread.CurrentThread;

            mt.Name = "Main";

            Console.WriteLine("【Main Thread】: Name—{0};IsBackground—{1};ThreadState—{2}", mt.Name, mt.IsBackground.ToString(), mt.ThreadState.ToString());

            Console.WriteLine("Main thread end.");

            Console.WriteLine();

            //主執行緒沒有結束,後臺執行緒繼續執行~~
            //Console.ReadKey();

與子執行緒委託對應的方法

public static void BackGroundThreadWorker()
{
            var bc = System.Threading.Thread.CurrentThread;

            bc.Name = "Background";

            Console.WriteLine();

            Console.WriteLine("【Background Thread】:Name—{0};IsBackground—{1};ThreadState—{2}", bc.Name, bc.IsBackground.ToString(), bc.ThreadState.ToString());

            System.Threading.Thread.Sleep(10000);

            Console.WriteLine("Background thread end.");
}

<1>我們執行以上程式,發現主執行緒(前臺執行緒)的資訊顯示後,程式直接結束,後臺執行緒也就結束,所以不顯示資訊。

<2>解開以下注釋,使得主執行緒在等待,所以大約10s後,子執行緒資訊顯示。

//主執行緒沒有結束,後臺執行緒繼續執行~~
            Console.ReadKey();

  

相關文章