Java 教程

Java 控制語句

面向物件程式設計

Java 內建類

Java 檔案處理

Java 錯誤與異常

Java 多執行緒

Java 同步

Java 網路程式設計

Java 集合

Java 介面

Java 資料結構

Java 集合演算法

高階 Java

Java 雜項

Java API與框架

Java 類引用

Java 有用資源

Java - 執行緒池



執行緒池

執行緒池是預初始化執行緒的集合。執行緒池背後的總體思路是在方法啟動時形成多個執行緒並將它們放入池中,在那裡它們等待工作。當伺服器接收到服務請求時,它會從該池中喚醒一個執行緒(如果可用)並將服務請求傳遞給它。執行緒完成服務後,它返回到池中並等待更多工作。如果池中沒有可用的執行緒,則伺服器將等待直到一個執行緒空閒。

為什麼在 Java 中使用執行緒池?

  • 它節省時間,因為無需建立新執行緒。

  • 它用於ServletJSP,其中容器建立一個執行緒池來處理請求。

在 Java 中建立執行緒池

Java 提供的java.util.concurrent.Executors類提供了一些建立執行緒池的方法。

Executors 類方法

以下是此類中一些重要且有用的方法,用於建立執行緒池:

序號 方法和描述
1

public static ExecutorService newCachedThreadPool()

建立一個執行緒池,該執行緒池根據需要建立新執行緒,但在可用時將重用先前構造的執行緒。

2

public static ExecutorService newFixedThreadPool(int nThreads)

建立一個執行緒池,該執行緒池重用固定數量的執行緒,這些執行緒從共享的無界佇列中獲取操作。

3

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

建立一個執行緒池,該執行緒池可以安排命令在給定延遲後執行,或定期執行。

4

public static ExecutorService newWorkStealingPool()

使用所有可用的處理器作為其目標並行級別來建立一個工作竊取執行緒池。

使用 newFixedThreadPool() 方法建立執行緒池

透過呼叫 Executors 類的靜態 newFixedThreadPool() 方法獲得固定執行緒池。

語法

ExecutorService fixedPool = Executors.newFixedThreadPool(2);

其中:

  • 最多 2 個執行緒將處於活動狀態以處理任務。

  • 如果提交超過 2 個執行緒,則它們將保留在佇列中,直到執行緒可用。

  • 如果執行緒由於執行期間發生故障而在關閉執行程式之前終止,則會建立一個新執行緒來代替它。

  • 任何執行緒都存在,直到池關閉。

示例:使用 newFixedThreadPool() 方法建立執行緒池

下面的 TestThread 程式顯示了使用 Executors newFixedThreadPool() 方法建立兩個執行緒的執行緒池的用法。我們使用 ThreadPoolExecutor 物件並使用 newFixedThreadPool(2) 初始化,這是一個大小為 2 的固定執行緒池。然後我們列印執行緒池的各種屬性。然後我們將一些執行緒新增到執行程式中,然後列印執行緒池的相同屬性以反映更改。

package com.tutorialspoint;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThread {
	
   public static void main(final String[] arguments) throws InterruptedException {
      ExecutorService executor = Executors.newFixedThreadPool(2);

      // Cast the object to its class type
      ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

      //Stats before tasks execution
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.submit(new Task());
      executor.submit(new Task());
	  executor.submit(new Task());
      executor.submit(new Task());

      //Stats after tasks execution
      System.out.println("Core threads: " + pool.getCorePoolSize());
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.shutdown();
   }  

   static class Task implements Runnable {

      public void run() {
         
         try {
            Long duration = (long) (Math.random() * 5);
            System.out.println("Running Task! Thread Name: " +
               Thread.currentThread().getName());
               TimeUnit.SECONDS.sleep(duration);
            
            System.out.println("Task Completed! Thread Name: " +
               Thread.currentThread().getName());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}

輸出

Largest executions: 0
Maximum allowed threads: 2
Current threads in pool: 0
Currently executing threads: 0
Total number of threads(ever scheduled): 0
Core threads: 2
Largest executions: 2
Maximum allowed threads: 2
Current threads in pool: 2
Currently executing threads: 2
Total number of threads(ever scheduled): 4
Running Task! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1

這裡,雖然我們提交了四個執行緒,但只執行了兩個執行緒,因為執行緒池被固定為只接受兩個執行緒。

使用 newCachedThreadPool() 方法建立執行緒池

透過呼叫 Executors 類的靜態 newCachedThreadPool() 方法獲得快取執行緒池。

語法

ExecutorService executor = Executors.newCachedThreadPool();

其中:

  • newCachedThreadPool 方法建立一個具有可擴充套件執行緒池的執行程式。

  • 此類執行程式適用於啟動許多短暫任務的應用程式。

示例:使用 newCachedThreadPool() 方法建立執行緒池

下面的 TestThread 程式演示瞭如何使用 Executors 的 newCachedThreadPool() 方法建立一個可擴充套件的執行緒池。我們使用 ThreadPoolExecutor 物件並用 newCachedThreadPool() 初始化它。然後我們列印執行緒池的各種屬性。之後我們向執行器新增一些執行緒,然後再次列印執行緒池的屬性以反映這些變化。

package com.tutorialspoint;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TestThread {
	
   public static void main(final String[] arguments) throws InterruptedException {
      ExecutorService executor = Executors.newCachedThreadPool();

      // Cast the object to its class type
      ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;

      //Stats before tasks execution
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.submit(new Task());
      executor.submit(new Task());
	  executor.submit(new Task());
      executor.submit(new Task());

      //Stats after tasks execution
      System.out.println("Core threads: " + pool.getCorePoolSize());
      System.out.println("Largest executions: "
         + pool.getLargestPoolSize());
      System.out.println("Maximum allowed threads: "
         + pool.getMaximumPoolSize());
      System.out.println("Current threads in pool: "
         + pool.getPoolSize());
      System.out.println("Currently executing threads: "
         + pool.getActiveCount());
      System.out.println("Total number of threads(ever scheduled): "
         + pool.getTaskCount());

      executor.shutdown();
   }  

   static class Task implements Runnable {

      public void run() {
         
         try {
            Long duration = (long) (Math.random() * 5);
            System.out.println("Running Task! Thread Name: " +
               Thread.currentThread().getName());
               TimeUnit.SECONDS.sleep(duration);
            
            System.out.println("Task Completed! Thread Name: " +
               Thread.currentThread().getName());
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
   }
}

輸出

Largest executions: 0
Maximum allowed threads: 2147483647
Current threads in pool: 0
Currently executing threads: 0
Total number of threads(ever scheduled): 0
Core threads: 0
Largest executions: 4
Maximum allowed threads: 2147483647
Current threads in pool: 4
Currently executing threads: 4
Total number of threads(ever scheduled): 4
Running Task! Thread Name: pool-1-thread-2
Running Task! Thread Name: pool-1-thread-4
Running Task! Thread Name: pool-1-thread-3
Running Task! Thread Name: pool-1-thread-1
Task Completed! Thread Name: pool-1-thread-3
Task Completed! Thread Name: pool-1-thread-4
Task Completed! Thread Name: pool-1-thread-2
Task Completed! Thread Name: pool-1-thread-1

使用 newScheduledThreadPool() 方法建立執行緒池

透過呼叫 Executors 類的靜態方法 newScheduledThreadPool() 獲得一個排程執行緒池。

語法

ExecutorService executor = Executors.newScheduledThreadPool(1);

示例:使用 newScheduledThreadPool() 方法建立執行緒池

下面的 TestThread 程式演示瞭如何使用 Executors 的 newScheduledThreadPool() 方法建立一個執行緒池。我們使用 ScheduledExecutorService 物件作為排程器,並用 newScheduledThreadPool() 初始化它。我們建立了一個 ScheduledFuture 物件來排程一個任務,該任務在初始延遲兩秒後每兩秒執行一次。使用排程器,我們將任務計劃執行十秒鐘。

package com.tutorialspoint;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class TestThread {

   public static void main(final String[] arguments) throws InterruptedException {
      final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

      final ScheduledFuture<?> beepHandler = 
         scheduler.scheduleAtFixedRate(new BeepTask(), 2, 2, TimeUnit.SECONDS);

      scheduler.schedule(new Runnable() {

         @Override
         public void run() {
            beepHandler.cancel(true);
            scheduler.shutdown();			
         }
      }, 10, TimeUnit.SECONDS);
   }  

   static class BeepTask implements Runnable {

      public void run() {
         System.out.println("beep");      
      }
   }
}

輸出

beep
beep
beep
beep
beep
廣告