Java Executors詳解

Java的多線程編程一直被廣泛使用和研究。它提供了許多方式來管理和控制線程的行為。但是這些功能並不足以方便地進行線程管理。在這種情況下,Java的並發庫提供了一種解決辦法,即使用java.util.concurrent.Executors類來管理線程。它使線程管理變得更加簡單、易於理解和實現。本文將從多個方面對Java Executors進行詳細的介紹。

一、線程池

線程池是一種執行多個任務的方式,使用線程池可以避免創建線程的開銷,以及將任務排隊等待的時間,從而提高程序的響應速度和性能。Java的線程池管理器類是java.util.concurrent.ExecutorService介面。下面是一個實現線程池的示例:

“`java
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
Runnable worker = new MyRunnable(i);
executor.execute(worker);
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
“`

這裡使用newFixedThreadPool方法創建一個固定大小的線程池。該線程池有5個線程。然後,循環運行10個任務。這些任務由MyRunnable類實現,實現了Runnable介面。execute()方法將每個任務提交給線程池,線程池會從線程池中的空閑線程中選擇一個線程來執行它們。最後,關閉線程池,並等待所有任務完成。注意,這裡的線程池最大可用線程數是5個。如果提交10個任務,則前5個將立即開始,而剩餘5個任務將排隊等待線程可用。

二、ScheduledExecutorService

Java的ScheduledExecutorService介面提供了一種調度執行任務的機制。下面是一個使用ScheduledExecutorService的示例:

“`java
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
ScheduledFuture scheduledFuture =
executor.scheduleAtFixedRate(new MyRunnable(), 1, 5, TimeUnit.SECONDS);
“`

這裡創建了一個大小為2的ScheduledExecutorService。然後使用scheduleAtFixedRate方法將任務提交給它。任務由MyRunnable實現。scheduleAtFixedRate表示每隔5秒鐘執行一次任務。這裡,需要注意的是,它初始延遲時間為1秒,因此,任務將在1秒後就開始執行。返回值是ScheduledFuture,它表示定期調度任務的結果和控制。可以使用以下代碼取消執行:

“`java
scheduledFuture.cancel(true);
“`

三、Callable和Future

Callable是一個帶有類型參數的介面,可以使用它來執行一個返回類型的非同步任務。上面的代碼已經使用了Runnable測試任務的執行。Callable並行計算的執行可以使用Future類。Future是一個帶有類型參數的介面,用於獲取並處理非同步任務的結果。

下面是一個使用Callable和Future的示例:

“`java
ExecutorService executor = Executors.newSingleThreadExecutor();
Future future = executor.submit(new Callable() {
@Override
public Integer call() throws Exception {
int count = 0;
for (int i = 0; i < 100; i++) {
count += i;
}
return count;
}
});
try {
System.out.println("result : " + future.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
executor.shutdown();
“`

這裡,使用newSingleThreadExecutor方法創建一個只有單個線程的線程池。這個線程池將執行一個返回類型為Integer的非同步任務,這個任務是一個Callable實現。submit()方法提交任務,並返回一個Future對象。然後,通過調用get()方法等待非同步任務完成並獲取結果。最後,關閉線程池。

四、CompletionService

CompletionService是一種在完成任務時返回結果的一種更高級的機制。CompletionService表示處理線程執行結果的一組隊列。它提供了一個帶有隊列的ExecutorService的實現,可以使用它來獲取已完成任務的結果。CompletionService和Future都可以用於獲取任務的結果,但CompletionService可以更多地控制任務的執行和獲取它們的結果。

下面是一個使用CompletionService的示例:

“`java
ExecutorService executor = Executors.newFixedThreadPool(5);
CompletionService completionService = new ExecutorCompletionService(executor);
for (int i = 0; i < 10; i++) {
final int taskId = i;
completionService.submit(new Callable() {
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
return taskId;
}
});
}
for (int i = 0; i < 10; i++) {
try {
System.out.println(completionService.take().get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
“`

這裡創建一個固定大小為5的線程池。然後,使用ExecutorCompletionService代替CompletionService,以將任務提交給它。這個示例將提交執行10個任務,每個任務執行2秒鐘。當任務完成時,take()方法將返回一個Future對象。使用get()方法等待非同步任務完成並獲取它的結果。最後,關閉線程池。

五、ForkJoinPool

Java的ForkJoinPool類是一個特殊的線程池,它可以重用線程,以便更好地利用CPU和內存資源。ForkJoinPool的主要設計目標是支持分治任務,例如在QuickSort或合併排序中使用。下面是一個使用ForkJoinPool的示例:

“`java
class ForkJoinMergeSort<T extends Comparable> extends RecursiveAction {
private T[] array;
private int start;
private int end;

public ForkJoinMergeSort(T[] array, int start, int end) {
super();
this.array = array;
this.start = start;
this.end = end;
}

@Override
protected void compute() {
if (end – start < 2) {
return;
}
int middle = (start + end) / 2;
invokeAll(new ForkJoinMergeSort(array, start, middle),
new ForkJoinMergeSort(array, middle, end));
merge(array, start, middle, end);
}

private void merge(T[] array, int start, int middle, int end) {
T[] tempArray = (T[]) new Comparable[end – start];
int i = start;
int j = middle;
int k = 0;
while (i < middle && j < end) {
tempArray[k++] = array[i].compareTo(array[j]) < 0 ? array[i++] : array[j++];
}
while (i < middle) {
tempArray[k++] = array[i++];
}
while (j < end) {
tempArray[k++] = array[j++];
}
System.arraycopy(tempArray, 0, array, start, tempArray.length);
}
}

public class ForkJoinPoolDemo {
public static void main(String[] args) {
Integer[] array = { 3, 56, 23, 1, 5, 34, 78, 2, 45, 99 };
ForkJoinPool pool = new ForkJoinPool();
ForkJoinMergeSort task = new ForkJoinMergeSort(array, 0, array.length);
pool.invoke(task);
pool.shutdown();
System.out.println(Arrays.toString(array));
}
}
“`

這裡實現一個單核心的歸併排序演算法,並使用ForkJoinPool類執行演算法。ForkJoinPool從內部維護線程池,遞歸地拆分任務,將它們分配給可用的線程,當線程完成任務時將結果匯總。在這裡,元素列表被遞歸地劃分為子列表,直到列表元素數量為1,然後逐步合併這些子列表,直到完成排序。

以上就是Java Executors的詳細介紹。它是Java多線程編程中的一個重要組成部分,並且提供了許多有用的實用程序,使線程編程變得更加容易和高效。

原創文章,作者:SMPB,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/143624.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
SMPB的頭像SMPB
上一篇 2024-10-22 23:34
下一篇 2024-10-22 23:34

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java Bean載入過程

    Java Bean載入過程涉及到類載入器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean載入的過程。 一、類載入器 類載入器是Java虛擬機…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字元串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字元串中是否存在多個指定字元: 一、字元串遍歷 字元串是Java編程中非常重要的一種數據類型。要判斷字元串中是否存在多個指定字元…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論