多線程

什麼是線程?

英文:Thread
  每個正在系統上運行的程序都是一個
進程。每個進程包含一到多個線程。進程也可能是整個程序或者是部分程序的動態執行。線程是一組指令的集合,或者是程序的特殊段,它可以在程序裏獨立執行。也可以把它理解爲代碼運行的上下文。所以線程基本上是輕量級的進程,它負責在單個程序裏執行多任務。通常由操作系統負責多個線程的調度和執行。
  線程是程序中一個單一的順序控制流程.在單個程序中同時運行多個線程完成不同的工作,稱爲多線程.
  線程和進程的區別在於,子進程和父進程有不同的代碼和數據空間,而多個線程則共享數據空間,每個線程有自己的執行堆棧和程序計數器爲其執行上下文.多線程主要是爲了節約CPU時間,發揮利用,根據具體情況而定. 線程的運行中需要使用計算機的內存資源和CPU。

什麼是多線程?

 多線程是爲了同步完成多項任務,不是爲了提高運行效率,而是爲了提高資源使用效率來提高系統的效率。線程是在同一時間需要完成多項任務的時候實現的。

 

  使用線程的好處有以下幾點:

 

  ·使用線程可以把佔據長時間的程序中的任務放到後臺去處理

 

  ·用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發某些事件的處理,可以彈出一個進度條來顯示處理的進度

 

  ·程序的運行速度可能加快

 

  ·在一些等待的任務實現上如用戶輸入、文件讀寫和網絡收發數據等,線程就比較有用了。在這種情況下可以釋放一些珍貴的資源如內存佔用等等。

 

  還有其他很多使用多線程的好處,這裏就不一一說明了。

 

  一些線程模型的背景

 

  可以重點討論一下在Win32環境中常用的一些模型。

 

  ·單線程模型

 

  在這種線程模型中,一個進程中只能有一個線程,剩下的進程必須等待當前的線程執行完。這種模型的缺點在於系統完成一個很小的任務都必須佔用很長的時間。

 

  ·塊線程模型(單線程多塊模型STA)

 

  這種模型裏,一個程序裏可能會包含多個執行的線程。在這裏,每個線程被分爲進程裏一個單獨的塊。每個進程可以含有多個塊,可以共享多個塊中的數據。程序規定了每個塊中線程的執行時間。所有的請求通過Windows消息隊列進行串行化,這樣保證了每個時刻只能訪問一個塊,因而只有一個單獨的進程可以在某一個時刻得到執行。這種模型比單線程模型的好處在於,可以響應同一時刻的多個用戶請求的任務而不只是單個用戶請求。但它的性能還不是很好,因爲它使用了串行化的線程模型,任務是一個接一個得到執行的。

 

  ·多線程塊模型(自由線程塊模型)

 

  多線程塊模型(MTA)在每個進程裏只有一個塊而不是多個塊。這單個塊控制着多個線程而不是單個線程。這裏不需要消息隊列,因爲所有的線程都是相同的塊的一個部分,並且可以共享。這樣的程序比單線程模型和STA的執行速度都要塊,因爲降低了系統的負載,因而可以優化來減少系統idle的時間。這些應用程序一般比較複雜,因爲程序員必須提供線程同步以保證線程不會併發的請求相同的資源,因而導致競爭情況的發生。這裏有必要提供一個鎖機制。但是這樣也許會導致系統死鎖的發生。

 

  進程和線程都是操作系統的概念。進程是應用程序的執行實例,每個進程是由私有的虛擬地址空間、代碼、數據和其它各種系統資源組成,進程在運行過程中創建的資源隨着進程的終止而被銷燬,所使用的系統資源在進程終止時被釋放或關閉。

 

  線程是進程內部的一個執行單元。系統創建好進程後,實際上就啓動執行了該進程的主執行線程,主執行線程以函數地址形式,比如說main或WinMain函數,將程序的啓動點提供給Windows系統。主執行線程終止了,進程也就隨之終止。

 

  每一個進程至少有一個主執行線程,它無需由用戶去主動創建,是由系統自動創建的。用戶根據需要在應用程序中創建其它線程,多個線程併發地運行於同一個進程中。一個進程中的所有線程都在該進程的虛擬地址空間中,共同使用這些虛擬地址空間、全局變量和系統資源,所以線程間的通訊非常方便,多線程技術的應用也較爲廣泛。多線程可以實現並行處理,避免了某項任務長時間佔用CPU時間。要說明的一點是,目前大多數的計算機都是單處理器(CPU)的,爲了運行所有這些線程,操作系統爲每個獨立線程安排一些CPU時間,操作系統以輪換方式向線程提供時間片,這就給人一種假象,好象這些線程都在同時運行。由此可見,如果兩個非常活躍的線程爲了搶奪對CPU的控制權,在線程切換時會消耗很多的CPU資源,反而會降低系統的性能。這一點在多線程編程時應該注意。Win32 SDK函數支持進行多線程的程序設計,並提供了操作系統原理中的各種同步、互斥和臨界區等操作。Visual C++ 6.0中,使用MFC類庫也實現了多線程的程序設計,使得多線程編程更加方便

多線程在.NET裏如何工作?

  在本質上和結構來說,.NET是一個多線程的環境。有兩種主要的多線程方法是.NET所提倡的:使用ThreadStart來開始你自己的進程,直接的(使用ThreadPool.QueueUserWorkItem)或者間接的(比如Stream.BeginRead,或者調用BeginInvoke)使用ThreadPool類。一般來說,你可以"手動"爲長時間運行的任務創建一個新的線程,另外對於短時間運行的任務尤其是經常需要開始的那些,進程池是一個非常好的選擇。進程池可以同時運行多個任務,還可以使用框架類。對於資源緊缺需要進行同步的情況來說,它可以限制某一時刻只允許一個線程訪問資源。這種情況可以視爲給線程實現了鎖機制。線程的基類是System.Threading。所有線程通過CLI來進行管理。

 

  ·創建線程:

 

  創建一個新的Thread對象的實例。Thread的構造函數接受一個參數:

 

  Thread DummyThread = new Thread( new ThreadStart(dummyFunction) );

 

  ·執行線程:

 

  使用Threading命名空間裏的start方法來運行線程:

 

  DummyThread.Start ();

 

  ·組合線程:

 

  經常會出現需要組合多個線程的情況,就是當某個線程需要其他線程的結束來完成自己的任務。假設DummyThread必須等待DummyPriorityThread來完成自己的任務,只需要這樣做:

 

  DummyPriorityThread.Join() ;

 

  ·暫停線程:

 

  使得線程暫停給定的秒

 

  DummyPriorityThread.Sleep(<Time in Second>);

 

  ·中止線程:

 

  如果需要中止線程可以使用如下的代碼:

 

  DummyPriorityThread.Abort();

 

  ·同步

 

  經常會遇到需要在線程間進行同步的情況,下面的代碼給出了一些方法:

 

  using System;

 

  using System.Threading;

 

  namespace SynchronizationThreadsExample

 

  {

 

  class SynchronizationThreadsExample

 

  {

 

  private int counter = 0;

 

  static void Main( )

 

  {

 

  SynchronizationThreadsExample STE = new SynchronizationThreadsExample();

 

  STE.ThreadFunction( );

 

  }

 

  public void ThreadFunction ( )

 

  {

 

  Thread DummyThread = new Thread( new ThreadStart(SomeFunction)) ;

 

  DummyThread.IsBackground=true;

 

  DummyThread.Name = "First Thread";

 

  DummyThread.Start( );

 

  Console.WriteLine("Started thread ", DummyThread.Name);

 

  Thread DummyPriorityThread = new Thread( new ThreadStart(SomeFunction) );

 

  DummyPriorityThread.IsBackground=true;

 

  DummyPriorityThread.Name = "Second Thread";

 

  DummyPriorityThread.Start( );

 

  Console.WriteLine("Started thread ", DummyPriorityThread.Name);

 

  DummyThread.Join( );

 

  DummyPriorityThread.Join( );

 

  }

 

  public void SomeFunction( )

 

  {

 

  try

 

  {

 

  while (counter < 10)

 

  {

 

  int tempCounter = counter;

 

  tempCounter ++;

 

  Thread.Sleep(1);

 

  counter = tempCounter;

 

  Console.WriteLine( "Thread . SomeFunction: "+Thread.CurrentThread.Name+counter);

 

  }

 

  }

 

  catch (ThreadInterruptedException Ex)

 

  {

 

  Console.WriteLine( "Exception in thread "+Thread.CurrentThread.Name);

 

  }

 

  finally

 

  {

 

  Console.WriteLine( "Thread Exiting. "+Thread.CurrentThread.Name);

 

  }

 

  }

 

  }

 

  }

 

  ·使用Interlock

 

  C#提供了一個特殊的類叫做interlocked,就是提供了鎖機制的實現,可以加入如下的代碼實現鎖機制:

 

  Interlocked.SomeFunction (ref counter);

 

  ·使用鎖

 

  這是爲了鎖定代碼關鍵區域以進行同步,鎖定代碼如下:

 

  lock (this){ Some statements ;}

 

  ·使用Monitor

 

  當有需要進行線程管理的時候可以使用:

 

  Monitor.Enter(this);

 

  其他也有一些方法進行管理,這裏就不一一提及了。

 

  線程的缺點

 

  線程自然也有缺點,以下列出了一些:

 

  ·如果有大量的線程,會影響性能,因爲操作系統需要在他們之間切換;

 

  ·更多的線程需要更多的內存空間

 

  ·線程會給程序帶來更多的bug,因此要小心使用

 

  ·線程的中止需要考慮其對程序運行的影響

 

  ·通常塊模型數據是在多個線程間共享的,需要一個合適的鎖系統替換掉數據共享

 

  參考鏈接:

 

  http://hi.baidu.com/ce%5Fken/blog/item/c7e7ebc40fe265ca39db49a7.html

 

  http://hi.baidu.com/ce%5Fken/blog/item/70c5670f62592a2b6159f348.html

多線程在JAVA裏面的應用

  Java對多線程的支持是非常強大的,他屏蔽掉了許多的技術細節,讓我們可以輕鬆的開發多線程的應用程序。

 

  Java裏面實現多線程,有2個方法

 

  1 繼承 Thread類,比如

 

  class MyThread extends Thread {

 

  public void run() {

 

  // 這裏寫上線程的內容

 

  }

 

  public static void main(String[] args) {

 

  // 使用這個方法啓動一個線程

 

  new MyThread().start();

 

  }

 

  }

 

  2 實現 Runnable接口

 

  class MyThread implements Runnable{

 

  public void run() {

 

  // 這裏寫上線程的內容

 

  }

 

  public static void main(String[] args) {

 

  // 使用這個方法啓動一個線程

 

  new Thread(new MyThread()).start();

 

  }

 

  }

 

  一般鼓勵使用第二種方法,因爲Java裏面只允許單一繼承,但允許實現多個接口。第二個方法更加靈活。

實際意義

  一個採用了多線程技術的應用程序可以更好地利用系統資源。其主要優勢在於充分利用了CPU的空閒時間片,可以用儘可能少的時間來對用戶的要求做出響應,使得進程的整體運行效率得到較大提高,同時增強了應用程序的靈活性。更爲重要的是,由於同一進程的所有線程是共享同一內存,所以不需要特殊的數據傳送機制,不需要建立共享存儲區或共享文件,從而使得不同任務之間的協調操作與運行、數據的交互、資源的分配等問題更加易於解決

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章