最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java線程池中execute()和submit()兩個方法的區(qū)別(源碼&實戰(zhàn)全解析)

 更新時間:2026年03月21日 09:32:39   作者:J_liaty  
線程池是現(xiàn)代多線程編程中的重要工具,它能顯著提升任務(wù)處理效率并優(yōu)化系統(tǒng)資源,這篇文章主要介紹了Java線程池中execute()和submit()兩個方法區(qū)別的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

在 Java 并發(fā)編程中,線程池是核心技術(shù)之一,而 execute()submit() 是線程池最常用的兩個方法。很多開發(fā)者只停留在表面認(rèn)識——execute 拋異常,submit 返回 Future,但這種理解遠(yuǎn)遠(yuǎn)不夠。

本文將從源碼層面深度解析這兩個方法的本質(zhì)差異,并通過實戰(zhàn)案例演示它們的適用場景。

一、核心差異一覽

維度execute()submit()
返回值voidFuture
異常傳播任務(wù)內(nèi)異常會直接拋出到 UncaughtExceptionHandler,主線程無法感知異常被 FutureTask 捕獲并存儲,調(diào)用 get() 時才拋出 ExecutionException
任務(wù)類型僅支持 Runnable支持 Runnable 和 Callable
適用場景不關(guān)心結(jié)果的異步任務(wù)(如日志發(fā)送、數(shù)據(jù)清理)需要獲取結(jié)果或處理異常的任務(wù)(如計算、RPC 調(diào)用)
接口定義Executor 接口ExecutorService 接口

二、源碼層面解析

2.1 submit() 的源碼實現(xiàn)

// AbstractExecutorService.java
public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    // 關(guān)鍵點1:將 Runnable 包裝為 RunnableFuture
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);  // 關(guān)鍵點2:最終還是調(diào)用 execute()
    return ftask;    // 關(guān)鍵點3:返回 Future 對象
}

protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}

核心洞察submit() 本質(zhì)上是 execute() 的包裝器,它在調(diào)用 execute() 前做了兩件事:

  1. 任務(wù)包裝:將 Runnable/Callable 包裝成 FutureTask
  2. 返回句柄:給調(diào)用者一個 Future 對象用于獲取結(jié)果

2.2 execute() 的核心邏輯

// ThreadPoolExecutor.java
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();

    int c = ctl.get();

    // 1. workerCount < corePoolSize -> 創(chuàng)建核心線程
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }

    // 2. workerCount >= corePoolSize && workQueue 未滿 -> 入隊
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        if (!isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }

    // 3. workerCount >= corePoolSize && workQueue 已滿 -> 創(chuàng)建非核心線程
    else if (!addWorker(command, false))
        // 4. 都失敗 -> 拒絕策略
        reject(command);
}

執(zhí)行流程

  • 工作線程數(shù) < 核心線程數(shù) → 創(chuàng)建核心線程執(zhí)行
  • 工作線程數(shù) ≥ 核心線程數(shù),隊列未滿 → 任務(wù)入隊
  • 工作線程數(shù) ≥ 核心線程數(shù),隊列已滿 → 創(chuàng)建非核心線程
  • 都失敗 → 觸發(fā)拒絕策略

三、實戰(zhàn)場景對比

3.1 異常處理的根本差異

execute() 的異常陷阱:

ExecutorService executor = Executors.newFixedThreadPool(2);

executor.execute(() -> {
    throw new RuntimeException("任務(wù)異常");
});

// 主線程無法捕獲這個異常!
// 異常會直接拋出到線程池的 UncaughtExceptionHandler

submit() 的異常安全:

ExecutorService executor = Executors.newFixedThreadPool(2);

Future<?> future = executor.submit(() -> {
    throw new RuntimeException("任務(wù)異常");
});

try {
    future.get();  // 調(diào)用 get() 時才會拋出 ExecutionException
} catch (ExecutionException e) {
    System.out.println("捕獲到任務(wù)異常: " + e.getCause());
}

3.2 批量任務(wù)處理 - submit 優(yōu)勢場景

ExecutorService executor = Executors.newFixedThreadPool(4);
List<Future<Integer>> futures = new ArrayList<>();

// 提交多個任務(wù)
for (int i = 0; i < 10; i++) {
    final int num = i;
    futures.add(executor.submit(() -> compute(num)));
}

// 批量獲取結(jié)果
for (Future<Integer> future : futures) {
    try {
        System.out.println(future.get());
    } catch (Exception e) {
        System.out.println("任務(wù)執(zhí)行異常: " + e.getCause());
    }
}

private int compute(int num) {
    // 模擬計算任務(wù)
    return num * num;
}

3.3 超時控制 - submit 獨有能力

ExecutorService executor = Executors.newFixedThreadPool(2);

Future<String> future = executor.submit(() -> {
    Thread.sleep(5000);
    return "結(jié)果";
});

try {
    String result = future.get(2, TimeUnit.SECONDS);  // 2秒超時
    System.out.println(result);
} catch (TimeoutException e) {
    future.cancel(true);  // 中斷任務(wù)
    System.out.println("任務(wù)超時,已取消");
}

3.4 execute 的最佳實踐 - 異常監(jiān)控

// 設(shè)置全局異常處理器
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
    System.out.println("線程 " + t.getName() + " 發(fā)生異常: " + e);
});

ExecutorService executor = Executors.newFixedThreadPool(2);

executor.execute(() -> {
    throw new RuntimeException("異常會被 UncaughtExceptionHandler 捕獲");
});

四、性能考量

  • execute():略輕量,直接提交任務(wù),無需創(chuàng)建 FutureTask 對象
  • submit():因創(chuàng)建 FutureTask 有極小開銷,但在實際業(yè)務(wù)中差異可忽略
  • 建議:如果不需要返回值和異常處理,優(yōu)先使用 execute()

五、面試標(biāo)準(zhǔn)答案

問題: Java 線程池中 execute() 和 submit() 有什么區(qū)別?

標(biāo)準(zhǔn)回答:

  1. 核心差異:execute() 是 Executor 接口定義的基礎(chǔ)方法,用于提交不需要返回值的任務(wù);submit() 是 ExecutorService 擴(kuò)展的方法,可以提交 Callable/Runnable 并返回 Future 對象。

  2. 源碼層面:submit() 內(nèi)部將任務(wù)包裝成 FutureTask,然后調(diào)用 execute() 執(zhí)行,所以 execute() 是 submit() 的底層實現(xiàn)。

  3. 異常處理:這是最重要的區(qū)別——execute() 中任務(wù)的異常會直接拋出到線程池的異常處理器,主線程無法感知;submit() 中任務(wù)的異常被 FutureTask 捕獲存儲,只有調(diào)用 Future.get() 時才會拋出 ExecutionException,主線程可以統(tǒng)一處理。

  4. 適用場景:execute() 適合"提交即忘"的異步任務(wù)(如日志、清理);submit() 適合需要結(jié)果、超時控制或細(xì)粒度異常處理的任務(wù)。

  5. 性能考量:execute() 略輕量,submit() 因為創(chuàng)建 FutureTask 有極小開銷,但在實際業(yè)務(wù)中差異可忽略。

六、進(jìn)階思考

6.1 為什么 submit() 要返回 Future?

這是"控制權(quán)"的設(shè)計哲學(xué),調(diào)用者可以通過 Future 實現(xiàn)取消、超時、結(jié)果獲取等精細(xì)控制。

6.2 線程池的拒絕策略對兩者有區(qū)別嗎?

沒有,最終都是調(diào)用 execute(),拒絕策略統(tǒng)一生效。

6.3 如何既用 execute() 的輕量,又實現(xiàn)異常監(jiān)控?

可以自定義 ThreadPoolExecutor,重寫 afterExecute() 方法:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2, 4, 60, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>()
) {
    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if (t != null) {
            System.out.println("任務(wù)執(zhí)行異常: " + t);
        } else if (r instanceof Future<?>) {
            try {
                ((Future<?>) r).get();
            } catch (Exception e) {
                System.out.println("Future 異常: " + e.getCause());
            }
        }
    }
};

七、總結(jié)

這道題的深層考點是:是否理解 Java 并發(fā)框架中"任務(wù)"和"執(zhí)行"的分離設(shè)計,以及異常在不同線程上下文中的傳播機(jī)制。

  • execute():輕量級異步執(zhí)行,適合"提交即忘"場景
  • submit():功能完善,支持結(jié)果獲取、超時控制、異常統(tǒng)一處理

選擇建議

  • 不需要返回值 → 優(yōu)先 execute()
  • 需要返回值或異常處理 → 必須使用 submit()

到此這篇關(guān)于Java線程池中execute()和submit()兩個方法區(qū)別的文章就介紹到這了,更多相關(guān)Java線程池execute()和submit()區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解 maven的pom.xml用<exclusion>解決版本問題

    詳解 maven的pom.xml用<exclusion>解決版本問題

    這篇文章主要介紹了詳解 maven的pom.xml用<exclusion>解決版本問題的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • Java中的jinfo命令使用詳解

    Java中的jinfo命令使用詳解

    jinfo是JDK提供的一個可以實時查看Java虛擬機(jī)各種配置參數(shù)和系統(tǒng)屬性的命令行工具,本文給大家介紹下Java中的jinfo命令使用,感興趣的朋友一起看看吧
    2022-03-03
  • Spring BeanDefinition使用介紹

    Spring BeanDefinition使用介紹

    BeanDefinition是Spring框架中非常核心的概念,BeanDefinition是定義Bean的配置元信息接口,Spring根據(jù)BeanDefinition來定義Bean對象,簡單說就是對Bean信息的定義
    2023-01-01
  • java的繼承原理與實現(xiàn)方法詳解

    java的繼承原理與實現(xiàn)方法詳解

    這篇文章主要介紹了java的繼承原理與實現(xiàn)方法,結(jié)合實例形式詳細(xì)分析了Java繼承的概念、原理、用法及相關(guān)操作注意事項,需要的朋友可以參考下
    2019-05-05
  • Mybatis使用大于等于或小于等于進(jìn)行比較

    Mybatis使用大于等于或小于等于進(jìn)行比較

    本文主要介紹了Mybatis使用大于等于或小于等于進(jìn)行比較,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • SpringBoot?整合Security權(quán)限控制的初步配置

    SpringBoot?整合Security權(quán)限控制的初步配置

    這篇文章主要為大家介紹了SpringBoot?整合Security權(quán)限控制的初步配置實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • javaweb中Filter(過濾器)的常見應(yīng)用

    javaweb中Filter(過濾器)的常見應(yīng)用

    這篇文章主要介紹了javaweb中Filter的常見應(yīng)用,過濾器的使用方法,感興趣的小伙伴們可以參考一下
    2015-12-12
  • Java編程實現(xiàn)深度優(yōu)先遍歷與連通分量代碼示例

    Java編程實現(xiàn)深度優(yōu)先遍歷與連通分量代碼示例

    這篇文章主要介紹了Java編程實現(xiàn)深度優(yōu)先遍歷與連通分量代碼示例,
    2017-11-11
  • Java的方法和this關(guān)鍵字如何理解與應(yīng)用

    Java的方法和this關(guān)鍵字如何理解與應(yīng)用

    Java語言中的“方法”(Method)在其他語言當(dāng)中也可能被稱為“函數(shù)”(Function)。對于一些復(fù)雜的代碼邏輯,如果希望重復(fù)使用這些代碼,并且做到“隨時任意使用”,那么就可以將這些代碼放在一個大括號{}當(dāng)中,并且起一個名字。使用代碼的時候,直接找到名字調(diào)用即可
    2021-10-10
  • AndroidHttpClient使用Cookie應(yīng)用分析

    AndroidHttpClient使用Cookie應(yīng)用分析

    今天想把一個用使用了HttpClient的自動簽到小程序移植到Android上,還好Android的SDK自帶了HttpClient的包.當(dāng)然也可以繼續(xù)使用DefaultHttpClient,但用為Android定制的AndroidHttpClient自然更好
    2012-11-11

最新評論

诸城市| 垦利县| 萨嘎县| 水富县| 鞍山市| 梨树县| 镇赉县| 辽中县| 宣化县| 广宗县| 丽水市| 新郑市| 夏邑县| 泸溪县| 北碚区| 成都市| 九龙坡区| 黔江区| 汝城县| 长宁区| 博乐市| 奇台县| 南岸区| 北安市| 西乡县| 县级市| 乌什县| 普宁市| 全南县| 同仁县| 九龙坡区| 珲春市| 云阳县| 天台县| 越西县| 博爱县| 吴旗县| 平江县| 海晏县| 灵宝市| 托里县|