成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

線程池,坑中之王 !

開發 前端
線程池是 Java 中處理多線程的強大工具,但它不僅僅是“直接用就完事”的工具。很多小伙伴在用線程池時,因為配置不當或忽略細節,踩過許多坑。

前言

線程池是 Java 中處理多線程的強大工具,但它不僅僅是“直接用就完事”的工具。

很多小伙伴在用線程池時,因為配置不當或忽略細節,踩過許多坑。

今天跟大家一起聊聊線程池中容易踩的 10 個坑,以及如何避免這些坑,希望對你會有所幫助。

1. 直接使用 Executors 創建線程池

許多初學者在創建線程池時,直接使用 Executors 提供的快捷方法:

ExecutorService executor = Executors.newFixedThreadPool(10);

問題在哪?

  • 無界隊列:newFixedThreadPool 使用的隊列是 LinkedBlockingQueue,它是無界隊列,任務堆積可能會導致內存溢出。
  • 線程無限增長:newCachedThreadPool 會無限創建線程,在任務量激增時可能耗盡系統資源。

示例:內存溢出的風險

ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 0; i < 1000000; i++) {
    executor.submit(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

任務數遠大于線程數,導致任務無限堆積在隊列中,最終可能導致 OutOfMemoryError。

解決辦法

使用 ThreadPoolExecutor,并明確指定參數:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2,
    4,
    60L,
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(100), // 有界隊列
    new ThreadPoolExecutor.AbortPolicy() // 拒絕策略
);

2. 錯誤配置線程數

很多人隨意配置線程池參數,比如核心線程數 10,最大線程數 100,看起來沒問題,但這可能導致性能問題或資源浪費。

示例:錯誤配置導致的線程過載

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    10, // 核心線程數
    100, // 最大線程數
    60L,
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(10)
);

for (int i = 0; i < 1000; i++) {
    executor.submit(() -> {
        try {
            Thread.sleep(5000); // 模擬耗時任務
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
}

這種配置在任務激增時,會創建大量線程,系統資源被耗盡。

正確配置方式

根據任務類型選擇合理的線程數:

  • CPU 密集型:線程數建議設置為 CPU 核心數 + 1。
  • IO 密集型:線程數建議設置為 2 * CPU 核心數。

示例:

int cpuCores = Runtime.getRuntime().availableProcessors();
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    cpuCores + 1,
    cpuCores + 1,
    60L,
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(50)
);

3. 忽略任務隊列的選擇

任務隊列直接影響線程池的行為。如果選錯隊列類型,會帶來很多隱患。

常見隊列的坑

  • 無界隊列:任務無限堆積。
  • 有界隊列:隊列滿了會觸發拒絕策略。
  • 優先級隊列:容易導致高優先級任務頻繁搶占低優先級任務。

示例:任務堆積導致問題

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    2,
    4,
    60L,
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>()
);

for (int i = 0; i < 100000; i++) {
    executor.submit(() -> System.out.println(Thread.currentThread().getName()));
}

改進方法:用有界隊列,避免任務無限堆積。

new ArrayBlockingQueue<>(100);

4. 忘記關閉線程池

有些小伙伴用完線程池后,忘記調用 shutdown(),導致程序無法正常退出。

示例:線程池未關閉

ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> System.out.println("任務執行中..."));
// 線程池未關閉,程序一直運行

正確關閉方式

executor.shutdown();
try {
    if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
        executor.shutdownNow();
    }
} catch (InterruptedException e) {
    executor.shutdownNow();
}

5. 忽略拒絕策略

當任務隊列滿時,線程池會觸發拒絕策略,很多人不知道默認策略(AbortPolicy)會直接拋異常。

示例:任務被拒絕

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    1,
    1,
    60L,
    TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(2),
    new ThreadPoolExecutor.AbortPolicy() // 默認策略
);

for (int i = 0; i < 10; i++) {
    executor.submit(() -> System.out.println("任務"));
}

執行到第四個任務時會拋出 RejectedExecutionException。

改進:選擇合適的策略

  • CallerRunsPolicy:提交任務的線程自己執行。
  • DiscardPolicy:直接丟棄新任務。
  • DiscardOldestPolicy:丟棄最老的任務。

6. 任務中未處理異常

線程池中的任務拋出異常時,線程池不會直接拋出,導致很多問題被忽略。

示例:異常被忽略

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

解決方法

捕獲任務內部異常:

executor.submit(() -> {
    try {
        throw new RuntimeException("任務異常");
    } catch (Exception e) {
        System.err.println("捕獲異常:" + e.getMessage());
    }
});

自定義線程工廠:

ThreadFactory factory = r -> {
    Thread t = new Thread(r);
    t.setUncaughtExceptionHandler((thread, e) -> {
        System.err.println("線程異常:" + e.getMessage());
    });
    return t;
};

7. 阻塞任務占用線程池

如果線程池中的任務是阻塞的(如文件讀寫、網絡請求),核心線程會被占滿,影響性能。

示例:阻塞任務拖垮線程池

executor.submit(() -> {
    Thread.sleep(10000); // 模擬阻塞任務
});

改進方法

  • 減少任務的阻塞時間。
  • 增加核心線程數。
  • 使用異步非阻塞方式(如 NIO)。

8. 濫用線程池

線程池不是萬能的,某些場景直接使用 new Thread() 更簡單。

示例:過度使用線程池

一個簡單的短期任務:

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> System.out.println("執行任務"));
executor.shutdown();

這種情況下,用線程池反而復雜。

改進方式

new Thread(() -> System.out.println("執行任務")).start();

9. 未監控線程池狀態

很多人用線程池后,不監控其狀態,導致任務堆積、線程耗盡的問題被忽略。

示例:監控線程池狀態

System.out.println("核心線程數:" + executor.getCorePoolSize());
System.out.println("隊列大?。? + executor.getQueue().size());
System.out.println("已完成任務數:" + executor.getCompletedTaskCount());

結合監控工具(如 JMX、Prometheus),實現實時監控。

10. 動態調整線程池參數

有些人在線程池設計時忽略了參數調整的必要性,導致后期性能優化困難。

示例:動態調整核心線程數

executor.setCorePoolSize(20);
executor.setMaximumPoolSize(50);

實時調整線程池參數,能適應業務的動態變化。

總結

線程池是強大的工具,但如果我們日常工作中用得不好也非常容易踩坑。

這篇文章通過實際代碼示例,我們可以清楚看到線程池的問題所在及改進方法。

希望這些內容能幫你避免踩坑,寫出高質量的線程池代碼!

線程池用得好,效率杠杠的;用得不好,程序天天崩!

責任編輯:武曉燕 來源: 蘇三說技術
相關推薦

2022-08-16 08:27:20

線程毀線程異步

2025-06-06 02:00:00

2015-03-24 16:29:55

默認線程池java

2024-02-04 08:26:38

線程池參數內存

2024-08-13 08:48:50

2024-08-26 08:29:55

2025-05-06 09:32:13

2023-05-19 08:01:24

Key消費場景

2024-07-15 08:20:24

2020-12-10 08:24:40

線程池線程方法

2012-05-15 02:18:31

Java線程池

2023-10-13 08:20:02

Spring線程池id

2023-02-24 14:46:32

Java線程池編程

2025-01-09 11:24:59

線程池美團動態配置中心

2017-01-10 13:39:57

Python線程池進程池

2020-06-04 12:15:37

Go內存池對象池

2024-06-04 07:52:04

2023-06-07 13:49:00

多線程編程C#

2019-12-27 09:09:42

Tomcat線程池JDK

2024-03-28 12:51:00

Spring異步多線程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: www.日韩高清 | 亚洲精品久久久久久久不卡四虎 | 国产精品综合视频 | 精品日韩在线 | 久久精品小视频 | 欧美色欧美亚洲另类七区 | 国产精品久久久久久久久免费高清 | 久久精品色视频 | 欧美1级 | 91麻豆精品国产91久久久久久 | 欧美一级二级在线观看 | 一区二区三区国产好的精 | 日一区二区 | 97国产精品视频 | 亚洲+变态+欧美+另类+精品 | 99九色| 三级特黄特色视频 | 亚洲午夜精品 | 成人性视频在线播放 | 999观看免费高清www | 久久久久久国产精品免费免费 | 欧美精品成人一区二区三区四区 | 成人在线视频网址 | 午夜小视频在线播放 | 日韩影院一区 | 亚洲视频一区在线观看 | 麻豆久久久久久久久久 | 成人久久久久久久久 | 一区二区三区电影在线观看 | 欧美日韩国产一区 | 色天堂影院| 亚洲国产aⅴ成人精品无吗 综合国产在线 | 第四色播日韩第一页 | 伊人青青久久 | 亚洲精品乱码8久久久久久日本 | 国产精品成人在线播放 | 国产精品二区三区在线观看 | 欧美国产精品久久久 | 美女久久 | 成人午夜电影在线观看 | 不卡一区二区三区四区 |