首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 並發基礎實戰:分而治之 —— 循序、Thread.join、Future 與 Fork/Join 四種實現對比

     編輯:Java 相關知識

問題場景

在大型整數陣列中尋找最大值。採用分而治之:將陣列分塊,各塊並行求最大值,再合併結果。

版本一:循序執行(基準)

public class MaxNumberFinder {
    static final int THRESHOLD = 50;
    static int[] createArray(int n) { /* 隨機生成 */ }
    static int getMax(int[] a) { /* 線性掃描 */ }
    static int findMax(int[] a) {
        int[] maxs = new int[(a.length + THRESHOLD - 1) / THRESHOLD];
        for (int i = 0; i < a.length; i += THRESHOLD) {
            int end = Math.min(i + THRESHOLD, a.length);
            maxs[i / THRESHOLD] = getMax(Arrays.copyOfRange(a, i, end));
        }
        return maxs.length > THRESHOLD ? findMax(maxs) : getMax(maxs);
    }
}

版本二:Thread + join()

static int findMaxThread(int[] a) {
    int[] maxs = new int[...];
    List threads = new ArrayList<>();
    for (int i = 0; i < a.length; i += THRESHOLD) {
        final int idx = i / THRESHOLD;
        final int[] sub = Arrays.copyOfRange(a, i, Math.min(i + THRESHOLD, a.length));
        Thread t = new Thread(() -> maxs[idx] = getMax(sub));
        t.start(); threads.add(t);
    }
    for (Thread t : threads) try { t.join(); } catch (InterruptedException ignored) {}
    return maxs.length > THRESHOLD ? findMaxThread(maxs) : getMax(maxs);
}

缺點:大量線程創建/銷毀開銷、高層線程阻塞等待低層、難以控制併發度。

版本三:ExecutorService + Future

static final ExecutorService pool = Executors.newCachedThreadPool();
static int findMaxFuture(int[] a) {
    int[] maxs = new int[...];
    List> futures = new ArrayList<>();
    for (int i = 0; i < a.length; i += THRESHOLD) {
        final int[] sub = Arrays.copyOfRange(a, i, Math.min(i + THRESHOLD, a.length));
        futures.add(pool.submit(() -> getMax(sub)));
    }
    for (int i = 0; i < futures.size(); i++)
        try { maxs[i] = futures.get(i).get(); } catch (Exception ignored) {}
    return maxs.length > THRESHOLD ? findMaxFuture(maxs) : getMax(maxs);
}

Future.get() 隱含阻塞等待,效果等同 join(),但線程池複用線程,減少創建開銷。

版本四:Fork/Join 框架(JDK 7+)

class MaxTask extends RecursiveTask {
    private final int[] data;
    MaxTask(int[] d) { this.data = d; }
    @Override protected Integer compute() {
        if (data.length <= THRESHOLD) return getMax(data);
        int mid = data.length / 2;
        MaxTask left = new MaxTask(Arrays.copyOfRange(data, 0, mid));
        MaxTask right = new MaxTask(Arrays.copyOfRange(data, mid, data.length));
        invokeAll(left, right);
        return Math.max(left.join(), right.join());
    }
}
// 使用
ForkJoinPool pool = new ForkJoinPool();
int max = pool.invoke(new MaxTask(array));

優點:工作竊取演算法自動負載均衡、遞歸任務分解自然映射、API 簡潔、針對多核優化。

效能對比(作者測試環境)

  • 循序版本反而最快(任務極簡,並行開銷大於收益)。
  • Thread.join 明顯最慢。
  • Future 與 Fork/Join 難分伯仲。

核心啟示

  1. 分而治之需配合閾值:任務粒度太細,管理開銷超過並行收益。
  2. 優先使用成熟框架(Fork/Join、CompletableFuture、並行流)而非手動管理線程。
  3. 效能優化必須基於基準測試,理論分析不可靠。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved