Java 併發 - 概述



Java 是一種多執行緒程式語言,這意味著我們可以使用 Java 開發多執行緒程式。多執行緒程式包含兩個或多個可以併發執行的部分,每個部分可以同時處理不同的任務,從而最大限度地利用可用資源,尤其是在您的計算機有多個 CPU 的情況下。

根據定義,多工處理是指多個程序共享公共處理資源(例如 CPU)。多執行緒將多工處理的概念擴充套件到應用程式中,您可以在其中將單個應用程式中的特定操作細分為各個執行緒。每個執行緒都可以並行執行。作業系統不僅在不同的應用程式之間分配處理時間,而且還在應用程式中的每個執行緒之間分配處理時間。

多執行緒使您能夠以一種方式編寫程式碼,其中多個活動可以在同一程式中併發進行。

執行緒的生命週期

執行緒在其生命週期中經歷不同的階段。例如,執行緒誕生、啟動、執行,然後死亡。下圖顯示了執行緒的完整生命週期。

Java Thread

以下是生命週期的各個階段:

  • 新建 - 新執行緒從新建狀態開始其生命週期。它保持在此狀態,直到程式啟動執行緒。它也被稱為新生執行緒

  • 可執行 - 新生執行緒啟動後,執行緒變為可執行狀態。處於此狀態的執行緒被認為正在執行其任務。

  • 等待 - 有時,執行緒在等待另一個執行緒執行任務時會轉換到等待狀態。執行緒只有在另一個執行緒發出訊號讓等待執行緒繼續執行時才會轉換回可執行狀態。

  • 計時等待 - 可執行執行緒可以為指定的時間間隔進入計時等待狀態。處於此狀態的執行緒在該時間間隔到期或其等待的事件發生時轉換回可執行狀態。

  • 終止(死亡) - 可執行執行緒在完成其任務或以其他方式終止時進入終止狀態。

執行緒優先順序

每個 Java 執行緒都有一個優先順序,它可以幫助作業系統確定執行緒的排程順序。

Java 執行緒優先順序範圍在 MIN_PRIORITY(常量 1)和 MAX_PRIORITY(常量 10)之間。預設情況下,每個執行緒都賦予 NORM_PRIORITY(常量 5)的優先順序。

較高優先順序的執行緒對程式來說更重要,應在較低優先順序的執行緒之前分配處理器時間。但是,執行緒優先順序不能保證執行緒執行的順序,並且在很大程度上依賴於平臺。

透過實現 Runnable 介面建立執行緒

如果您的類旨在作為執行緒執行,那麼您可以透過實現Runnable介面來實現。您需要遵循三個基本步驟:

步驟 1

第一步,您需要實現Runnable介面提供的run()方法。此方法為執行緒提供了一個入口點,您將在此方法中放置您的完整業務邏輯。以下是run()方法的簡單語法:

public void run( )

步驟 2

第二步,您將使用以下建構函式例項化一個Thread物件:

Thread(Runnable threadObj, String threadName);

其中,threadObj是實現Runnable介面的類的例項,threadName是賦予新執行緒的名稱。

步驟 3

建立Thread物件後,您可以透過呼叫start()方法啟動它,該方法會執行對run()方法的呼叫。以下是start()方法的簡單語法:

void start();

示例

這是一個建立新執行緒並開始執行它的示例:

class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;

   RunnableDemo(String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      
      try {
      
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      RunnableDemo R1 = new RunnableDemo("Thread-1");
      R1.start();
      
      RunnableDemo R2 = new RunnableDemo("Thread-2");
      R2.start();
   }   
}

這將產生以下結果:

輸出

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.

透過擴充套件 Thread 類建立執行緒

建立執行緒的第二種方法是建立一個擴充套件Thread類的新類,使用以下兩個簡單的步驟。這種方法在處理使用Thread類中可用方法建立的多個執行緒方面提供了更大的靈活性。

步驟 1

您需要重寫Thread類中可用的run()方法。此方法為執行緒提供了一個入口點,您將在此方法中放置您的完整業務邏輯。以下是run()方法的簡單語法:

public void run( )

步驟 2

建立Thread物件後,您可以透過呼叫start()方法啟動它,該方法會執行對run()方法的呼叫。以下是start()方法的簡單語法:

void start( );

示例

以下是重寫為擴充套件Thread的前面程式:

class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   
   ThreadDemo(String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      
      try {

         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            
            // Let the thread sleep for a while.
            Thread.sleep(50);
         }
      } catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}

public class TestThread {

   public static void main(String args[]) {
      ThreadDemo T1 = new ThreadDemo("Thread-1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo("Thread-2");
      T2.start();
   }   
}

這將產生以下結果:

輸出

Creating Thread-1
Starting Thread-1
Creating Thread-2
Starting Thread-2
Running Thread-1
Thread: Thread-1, 4
Running Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 exiting.
Thread Thread-2 exiting.
廣告