SpringBoot 線程池 配置使用詳解

一、核心特性

Springboot 集成
支持 @Async 注解,簡化異步方法調用。
參數可配置化

核心線程數、最大線程數、隊列容量、拒絕策略等均可通過配置調整。
生命周期管理

實現 Lifecycle 接口,支持線程池的啟動和關閉(如應用關閉時優雅終止任務)。
任務裝飾器

支持通過 TaskDecorator 對任務進行裝飾(如傳遞上下文信息)

二、添加依賴

pom.xml 文件中添加 Spring Boot Starter AOP 依賴

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

三、參數詳解

通過 Spring 配置文件或 @Bean 定義線程池時,需設置以下關鍵參數:

參數名稱說明默認值
corePoolSize核心線程數,即使空閑也不會被回收1
maxPoolSize最大線程數,當隊列滿時創建新線程直到達到此值Integer.MAX_VALUE
queueCapacity任務隊列容量(使用 LinkedBlockingQueue 或 ArrayBlockingQueue)Integer.MAX_VALUE
keepAliveSeconds非核心線程的空閑存活時間(秒)60
threadNamePrefix線程名前綴,便于日志追蹤"task-executor-"
allowCoreThreadTimeOut是否允許核心線程超時回收false
rejectedExecutionHandler拒絕策略(如 AbortPolicy、CallerRunsPolicy)AbortPolicy(直接拋出異常)

四、配置線程池

@Configuration
@EnableAsync
public class ExecutorConfig {private static final Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);@Value("${async.executor.thread.core_pool_size}")private int corePoolSize;@Value("${async.executor.thread.max_pool_size}")private int maxPoolSize;@Value("${async.executor.thread.queue_capacity}")private int queueCapacity;@Value("${async.executor.thread.name.prefix}")private String namePrefix;@Bean(name = "asyncServiceExecutor")public Executor asyncServiceExecutor() {logger.info("start asyncServiceExecutor");ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//配置核心線程數executor.setCorePoolSize(corePoolSize);//配置最大線程數executor.setMaxPoolSize(maxPoolSize);//配置隊列大小executor.setQueueCapacity(queueCapacity);//配置線程池中的線程的名稱前綴executor.setThreadNamePrefix(namePrefix);// rejection-policy:當pool已經達到max size的時候,如何處理新任務// CALLER_RUNS:不在新線程中執行任務,而是有調用者所在的線程來執行executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());//執行初始化executor.initialize();return executor;}
}

@Value是我配置在?application.yml,可以參考配置,自由定義?

# 異步線程配置
# 配置核心線程數
async.executor.thread.core_pool_size = 5
# 配置最大線程數
async.executor.thread.max_pool_size = 5
# 配置隊列大小
async.executor.thread.queue_capacity = 99999
# 配置線程池中的線程的名稱前綴
async.executor.thread.name.prefix = async-service-

五、應用實踐

1、異步任務處理

創建一個服務類 AsyncService,并在其方法上使用 @Async 注解來定義異步任務:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class AsyncService {private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);@Async("taskExecutor")public void asyncTask(String taskName) {logger.info(Thread.currentThread().getName() + " 開始執行任務: " + taskName);try {Thread.sleep(2000); // 模擬耗時操作} catch (InterruptedException e) {Thread.currentThread().interrupt();logger.error("任務執行被中斷", e);} finally {logger.info(Thread.currentThread().getName() + " 任務執行完成: " + taskName);}}
}

創建一個控制器類 AsyncController,用于觸發異步任務(線程安全的)

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.concurrent.Future;@RestController
public class AsyncController {private static final Logger logger = LoggerFactory.getLogger(AsyncController.class);@Autowiredprivate AsyncService asyncService;@GetMapping("/trigger")public String triggerAsyncTasks() {logger.info("開始觸發異步任務");for (int i = 0; i < 10; i++) {asyncService.asyncTask("任務 " + i);}return "異步任務已觸發";}
}

創建一個監控組件 ThreadPoolMonitor,用于定期監控線程池的狀態

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;@Component
public class ThreadPoolMonitor {private static final Logger logger = LoggerFactory.getLogger(ThreadPoolMonitor.class);@Autowiredprivate ThreadPoolTaskExecutor taskExecutor;@Scheduled(fixedRate = 60000) // 每分鐘執行一次public void monitorThreadPool() {int activeCount = taskExecutor.getActiveCount();int poolSize = taskExecutor.getPoolSize();int corePoolSize = taskExecutor.getCorePoolSize();int maxPoolSize = taskExecutor.getMaxPoolSize();int queueSize = taskExecutor.getThreadPoolExecutor().getQueue().size();int completedTaskCount = taskExecutor.getThreadPoolExecutor().getCompletedTaskCount();logger.info("線程池狀態 - 活動線程數: {}, 當前線程數: {}, 核心線程數: {}, 最大線程數: {}, 隊列大小: {}, 已完成任務數: {}",activeCount, poolSize, corePoolSize, maxPoolSize, queueSize, completedTaskCount);// 檢查線程池是否接近飽和if (activeCount >= maxPoolSize * 0.8 || queueSize >= taskExecutor.getQueueCapacity() * 0.8) {logger.warn("線程池負載過高!請考慮優化配置或檢查任務執行情況");}}
}

?確保在啟動類上添加 @EnableAsync 注解,以啟用異步任務支持

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;@SpringBootApplication
@EnableAsync
public class AsyncDemoApplication {public static void main(String[] args) {SpringApplication.run(AsyncDemoApplication.class, args);}
}

測試:

啟動 Spring Boot 應用后,訪問 http://localhost:8080/trigger,即可看到異步任務在線程池中執行的情況,同時線程池的狀態也會定期輸出到日志中。

代碼說明

  • @EnableAsync 注解 :用于啟用 Spring 的異步方法執行支持,確保 Spring 容器能夠識別和處理帶有 @Async 注解的方法。

  • @Async 注解 :用于標注希望異步執行的方法,需指定所使用的線程池 Bean 的名稱,在本例中為 “taskExecutor”。當該方法被調用時,Spring 會將其提交到指定的線程池中執行。

  • ThreadPoolTaskExecutor :是 Spring 提供的一個線程池任務執行器,通過設置核心線程數、最大線程數、隊列容量等參數,可以根據應用的需求靈活地配置線程池。

  • 異步任務失敗處理 :通過自定義的拒絕策略,在線程池滿時記錄詳細信息并拋出異常,以便及時發現任務執行失敗的情況。

  • 線程池監控 :使用 @Scheduled 注解定期監控線程池的狀態,包括活動線程數、當前線程數、核心線程數、最大線程數、隊列大小和已完成任務數等,幫助開發者了解線程池的運行情況,以便及時進行優化和調整

2、高并發請求處理

在 Web 應用中處理大量并發請求,避免阻塞主線程

@RestController
public class MyController {@Autowiredprivate ThreadPoolTaskExecutor taskExecutor;@GetMapping("/process")public CompletableFuture<String> handleRequest() {return CompletableFuture.supplyAsync(() -> {// 耗時操作return "Result";}, taskExecutor);}}

3、定時任務調度

@EnableScheduling
@Configuration
public class SchedulerConfig {@Beanpublic ThreadPoolTaskScheduler taskScheduler() {ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();scheduler.setPoolSize(5);scheduler.setThreadNamePrefix("Scheduler-");return scheduler;}}@Service
public class ScheduledService {@Scheduled(fixedRate = 5000)public void scheduledTask() {// 定時任務邏輯}}

?

拒絕策略(Rejected Policies

當線程池和隊列均滿時,處理新任務的策略:

策略類行為描述
AbortPolicy直接拋出 RejectedExecutionException(默認)
CallerRunsPolicy由提交任務的線程直接執行任務(同步阻塞提交者)
DiscardPolicy靜默丟棄新任務,不拋異常
DiscardOldestPolicy丟棄隊列中最舊的任務,然后重試提交新任務

如下給出不同拒絕策略的配置類,請結合上面的配置類整合使用

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;@Configuration
public class ThreadPoolConfig {@Bean(name = "abortPolicyExecutor")public ThreadPoolTaskExecutor abortPolicyExecutor() {return createExecutor(new ThreadPoolExecutor.AbortPolicy());}@Bean(name = "callerRunsPolicyExecutor")public ThreadPoolTaskExecutor callerRunsPolicyExecutor() {return createExecutor(new ThreadPoolExecutor.CallerRunsPolicy());}@Bean(name = "discardPolicyExecutor")public ThreadPoolTaskExecutor discardPolicyExecutor() {return createExecutor(new ThreadPoolExecutor.DiscardPolicy());}@Bean(name = "discardOldestPolicyExecutor")public ThreadPoolTaskExecutor discardOldestPolicyExecutor() {return createExecutor(new ThreadPoolExecutor.DiscardOldestPolicy());}private ThreadPoolTaskExecutor createExecutor(ThreadPoolExecutor.RejectedExecutionHandler rejectedExecutionHandler) {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5); // 核心線程數executor.setMaxPoolSize(10); // 最大線程數executor.setQueueCapacity(100); // 隊列容量executor.setThreadNamePrefix("Task-Executor-"); // 線程名前綴executor.setRejectedExecutionHandler(rejectedExecutionHandler);executor.initialize();return executor;}
}

創建一個服務類 TaskService,用于執行任務

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class TaskService {@Async("abortPolicyExecutor")public void executeWithAbortPolicy(String taskName) {executeTask(taskName);}@Async("callerRunsPolicyExecutor")public void executeWithCallerRunsPolicy(String taskName) {executeTask(taskName);}@Async("discardPolicyExecutor")public void executeWithDiscardPolicy(String taskName) {executeTask(taskName);}@Async("discardOldestPolicyExecutor")public void executeWithDiscardOldestPolicy(String taskName) {executeTask(taskName);}private void executeTask(String taskName) {try {System.out.println(Thread.currentThread().getName() + " 開始執行任務: " + taskName);Thread.sleep(2000); // 模擬任務執行時間System.out.println(Thread.currentThread().getName() + " 任務執行完成: " + taskName);} catch (InterruptedException e) {Thread.currentThread().interrupt();System.err.println("任務執行被中斷: " + taskName);}}
}

創建一個控制器類 TaskController,用于觸發任務執行

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class TaskController {@Autowiredprivate TaskService taskService;@GetMapping("/trigger/abort")public String triggerAbortPolicy(@RequestParam String taskName) {taskService.executeWithAbortPolicy(taskName);return "任務已提交到使用 AbortPolicy 的線程池";}@GetMapping("/trigger/caller")public String triggerCallerRunsPolicy(@RequestParam String taskName) {taskService.executeWithCallerRunsPolicy(taskName);return "任務已提交到使用 CallerRunsPolicy 的線程池";}@GetMapping("/trigger/discard")public String triggerDiscardPolicy(@RequestParam String taskName) {taskService.executeWithDiscardPolicy(taskName);return "任務已提交到使用 DiscardPolicy 的線程池";}@GetMapping("/trigger/discardoldest")public String triggerDiscardOldestPolicy(@RequestParam String taskName) {taskService.executeWithDiscardOldestPolicy(taskName);return "任務已提交到使用 DiscardOldestPolicy 的線程池";}
}

啟動 Spring Boot 應用后,分別訪問以下 URL 來測試不同拒絕策略的行為:

  • http://localhost:8080/trigger/abort?taskName=任務1

  • http://localhost:8080/trigger/caller?taskName=任務2

  • http://localhost:8080/trigger/discard?taskName=任務3

  • http://localhost:8080/trigger/discardoldest?taskName=任務4

  • 代碼說明

  • 線程池配置

    • 使用 ThreadPoolTaskExecutor 創建線程池。

    • 配置了 4 個不同的線程池,每個線程池使用不同的拒絕策略。

    • 每個線程池的核心線程數為 5,最大線程數為 10,隊列容量為 100。

  • 拒絕策略

    • AbortPolicy:直接拋出 RejectedExecutionException

    • CallerRunsPolicy:由提交任務的線程直接執行任務。

    • DiscardPolicy:靜默丟棄新任務,不拋異常。

    • DiscardOldestPolicy:丟棄隊列中最舊的任務,然后重試提交新任務。

    • 任務執行

      • TaskService 類中的每個方法都使用 @Async 注解,并指定使用的線程池。

      • executeTask 方法模擬任務執行,包含一個 2 秒的睡眠時間。

      • 通過這個示例,你可以觀察不同拒絕策略在任務被拒絕時的行為。例如,當線程池滿時,AbortPolicy 會拋出異常,CallerRunsPolicy 會讓提交任務的線程執行任務,DiscardPolicy 會靜默丟棄任務,而 DiscardOldestPolicy 會丟棄最舊的任務并嘗試提交新任務

    • 6、最佳配置

    • · 合理設置線程池參數
      CPU 密集型任務:核心線程數 ≈ CPU 核心數
      I/O 密集型任務:核心線程數 ≈ CPU 核心數 * 2,并增大隊列容量。
      ·?避免隊列無限堆積
      設置合理的 queueCapacity,防止內存溢出(OOM)。
      · 統一異常處理
      通過 AsyncUncaughtExceptionHandler 捕獲異步任務中的異常:

    • @Configurationpublic class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();// ... 配置參數return executor;}@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return (ex, method, params) -> {// 處理異常};}}
      

      應用退出時,調用?shutdown()?并等待剩余任務執行完畢

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

      總結:

    • ThreadPoolTaskExecutor?是?Spring?生態中管理線程任務的利器,通過靈活的配置和與?Spring?的無縫集成,能夠高效處理異步任務、高并發請求和定時調度。合理設置參數、選擇拒絕策略,并結合監控手段,可顯著提升系統性能和穩定性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/85104.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/85104.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/85104.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Elasticsearch/OpenSearch MCP Quickstart

項目概述 elasticsearch-mcp-server 是一個基于 Model Context Protocol (MCP) 的服務器實現&#xff0c;提供了與 Elasticsearch 和 OpenSearch 交互的能力。該服務器允許用戶搜索文檔、分析索引以及管理集群&#xff0c;通過一系列工具函數實現這些功能。 項目結構 項目主…

《Elasticsearch 分布式搜索在聊天記錄檢索中的深度優化》

Elasticsearch 分布式搜索在聊天記錄檢索中的深度優化 引言 在現代聊天應用中&#xff0c;聊天記錄檢索面臨著數據量大、查詢復雜、實時性要求高的多重挑戰。以某社交平臺為例&#xff0c;其聊天記錄每天新增數千萬條&#xff0c;總數據量達百億級&#xff0c;用戶需要在海量…

CSS實現元素撐滿剩余空間的5種方法

CSS實現元素撐滿剩余空間的5種方法 &#x1f3a8; 在日常開發中&#xff0c;我們經常需要讓某個元素占據容器的剩余空間。這是一個常見的布局需求&#xff0c;比如側邊欄主內容區、頭部內容區底部等布局。本文將介紹5種不同的方法來實現這個需求&#xff0c;并分析各種方法的優…

[AI]從零開始的YOLO數據集增強教程

一、前言 不知道大家在訓練YOLO時有沒有遇到過這樣的情況&#xff0c;明明數據集已經準備了很多了&#xff0c;但是YOLO還是不認識某個物品&#xff0c;或者置信度低。那么有沒有辦法讓我們不制作新數據集的情況下讓代碼幫我們生成新的數據集來訓練模型呢&#xff1f;當然有&am…

軟件工程的相關名詞解釋

目錄 1. 軟件生命周期2.開源軟件3.軟件工程4.模塊化原則5.信息隱藏原則6.雙向追蹤7.原型8.軟件需求9.需求工程10.邊界類11.軟件實現&#xff08;的任務&#xff09;12.軟件缺陷13.回歸測試14.軟件β版15.軟件部署16.糾正性維護17.改善性維護18.適應性維護19.軟件邏輯老化 1. 軟…

2025.06.17【BUG】|多樣品VCF文件合并技巧及注意事項(以bcftools為例)

文章目錄 [toc]一、合并VCF的常用命令1.1 合并多個bgzip壓縮的VCF文件1.2 使用文件列表合并 二、合并前的準備與注意事項2.1 文件格式要求2.2 樣本名唯一性2.3 檢查文件模式匹配 三、常見報錯與解決方法3.1 報錯&#xff1a;Error: Duplicate sample names (sample1), use --fo…

包含30個APP客戶端UI界面的psd適用于旅游酒店項目

包含30個APP客戶端UI界面的psd適用于旅游酒店項目 此資源包含30個完全可編輯的psd界面組成。內容包括歡迎頁、登錄、注冊、首頁、搜索、側邊菜單、用戶中心、個人介紹、用戶空間、產品詳細信息、酒店預定、天氣情況等各種常用界面&#xff0c;您可以將其用于旅游酒店類的APP應用…

ArrayList源碼分析

目錄 ArrayList簡介 ArrayList和vector的區別&#xff08;了解即可&#xff09; ArrayList添加null值 ArrayList和LinkedList區別 ArrayList核心源碼解讀 ArrayList擴容機制分析 一步一分析ArrayList擴容機制 hugeCapacity()方法 System.arraycopy() Arrays.copyOf()方法 …

NX二次開發C#---通過Face找Edges,再通過Edges找Curve

文章介紹了一個名為AskFaceEdge的靜態方法&#xff0c;用于處理3D建模中的邊緣曲線生成。該方法通過NX Open API調用&#xff0c;主要功能是獲取指定面的邊緣并生成相應的曲線。方法接收兩個參數&#xff1a;faceTag&#xff08;面標簽&#xff09;和curveLoop&#xff08;曲線…

設計模式筆記_創建型_工廠模式

1. 工廠模式簡介 工廠模式是一種創建型設計模式&#xff0c;主要用于創建對象實例。 它通過定義一個接口或抽象類來創建對象&#xff0c;而不是直接實例化具體類&#xff0c;從而將對象的創建過程與使用過程分離。 工廠模式通常分為兩種類型&#xff1a; 簡單工廠模式&#x…

2025.6.16總結

工作&#xff1a;今天閉環了個遺留問題。在做專項評估時寫得太簡單&#xff0c;這讓測試經理質疑你的測試質量。如果換位思考&#xff0c;你是測試經理&#xff0c;你該怎么去把握風險和保證產品的質量&#xff0c;就知道寫得太簡單&#xff0c;沒有可信度。 找開發看了下后臺…

記錄:安裝VMware、Ubuntu、ROS2

安裝了VMware&#xff0c;就能夠在Windows系統裝安裝Ubuntu&#xff0c;使用Linux系統。安裝了Ubuntu&#xff0c;就能在里面安裝ROS2&#xff0c;之后寫代碼控制機器人兒。 安裝VMware 我安裝的是16 pro【具體是vmware16.2.4】&#xff0c;下載網站&#xff1a;VMware Works…

將后端數據轉換為docx文件

使用docx npm install docx 按照注釋處理數據并轉換為對應的bolb數據流 <template><Button type"primary" click"handleDocxCreate">{{buttonTitle || "報告生成"}}</Button> </template><script> import {Doc…

數據結構排序算法合集

快排 private static void quickSort(int[] ret) { quick(ret,0,ret.length-1); } private static void quick(int[] ret, int left, int right) { if(left>right) 記一下這里是大于等于 return; int pivot partition(ret,left,right); quick(ret…

【算法筆記】紅黑樹插入操作

紅黑樹插入與調整詳解 一、紅黑樹的五大性質 紅黑樹是一種自平衡的二叉搜索樹&#xff08;BST&#xff09;&#xff0c;其核心特性如下&#xff1a; 顏色屬性&#xff1a;每個節點非紅即黑根屬性&#xff1a;根節點必須為黑色葉子屬性&#xff1a;所有的 NIL 葉子節點都是黑…

認知計算革命:從算法創新到產業落地的AI專業核心應用全景

??一、自動化機器學習&#xff08;AutoML&#xff09;?? ??技術機理與產業實踐深度剖析?? ??神經網絡架構搜索&#xff08;NAS&#xff09;?? 強化學習方案&#xff1a;Google Brain的NASNet采用策略梯度優化卷積單元進化算法方案&#xff1a;DeepMind的AmeobaNe…

篇章十 論壇系統——業務開發——板塊和帖子

目錄 1.板塊 1.1 思路 1.2 實現邏輯 1.3 參數要求 1.4 實現步驟 1.Mapper.xml 2.Mapper.java 3.Service接口 4.Service實現 5.單元測試 6.Controller 7.測試API 8.前后端交互 2.帖子 1.1思路?編輯 1.2 參數要求 ?編輯 1.3 實現步驟 1.Mapper.xml 2.Mapper…

React Native 上線前的準備與企業實戰經驗總結

上線前的準備與企業實戰經驗總結 關鍵要點 熱更新簡化部署&#xff1a;CodePush 和 Expo OTA 允許快速推送 JavaScript 和資源更新&#xff0c;繞過應用商店審核&#xff0c;適合修復 Bug 或小規模功能迭代。監控與分析提升質量&#xff1a;Sentry 提供實時錯誤跟蹤&#xff…

【AI時代速通QT】第一節:C++ Qt 簡介與環境安裝

目錄 前言 一、為什么是 Qt&#xff1f;—— C 開發者的必備技能 二、Qt 的核心魅力&#xff1a;不止于跨平臺 2.1 優雅之一&#xff1a;代碼隔離&#xff0c;清晰明了 2.2 優雅之二&#xff1a;信號與槽&#xff08;Signal & Slot&#xff09;機制 2.3 優雅之三&…

pandas學習筆記

前言 總結才是知識&#xff0c;作者習慣不好&#xff0c;不會總結&#xff0c;導致函數一旦不使用就會忘記怎么使用&#xff0c;特此寫了本文&#xff0c;用于給自己一個復習的資料. 提示&#xff1a;如果你是小白&#xff0c;每個代碼請自己敲打。 一 pandas的介紹 Pandas is…