【Easylive】視頻刪除方法詳解:重點分析異步線程池使用

【Easylive】項目常見問題解答(自用&持續更新中…) 匯總版

方法整體功能

這個deleteVideo方法是一個綜合性的視頻刪除操作,主要完成以下功能:

  1. 權限驗證:檢查視頻是否存在及用戶是否有權限刪除
  2. 核心數據刪除:刪除視頻主信息、投稿信息
  3. 經濟系統調整:扣除用戶發布視頻獲得的硬幣
  4. 搜索索引清理:從Elasticsearch中移除文檔
  5. 異步清理關聯數據:使用線程池異步刪除分P視頻、彈幕、評論等關聯數據及物理文件

重點:異步線程池部分詳解

1. 線程池初始化

private static ExecutorService executorService = Executors.newFixedThreadPool(10);

? 線程池類型:固定大小線程池(10個線程)
? 特點
? 池中線程數量固定不變
? 適合已知并發量的穩定負載場景
? 超出線程數的任務會在隊列中等待
? 潛在問題
? 使用無界隊列(默認LinkedBlockingQueue),可能導致OOM
? 靜態變量生命周期與應用一致,可能造成線程泄漏

2. 異步任務執行邏輯

executorService.execute(() -> {// 異步任務代碼塊
});

? 任務封裝:使用Lambda表達式封裝Runnable任務
? 執行方式execute()方法提交任務到線程池
? 與事務的關系
? 異步任務在新線程中執行
? 不受主方法@Transactional注解影響,形成獨立的事務上下文
? 若異步操作需要事務,需在任務內部添加事務注解

3. 異步任務具體操作

(1) 查詢和刪除分P視頻
VideoInfoFileQuery videoInfoFileQuery = new VideoInfoFileQuery();
videoInfoFileQuery.setVideoId(videoId);
List<VideoInfoFile> videoInfoFileList = this.videoInfoFileMapper.selectList(videoInfoFileQuery);
videoInfoFileMapper.deleteByParam(videoInfoFileQuery);

? 操作順序:先查詢后刪除
? 目的:獲取文件路徑用于后續物理刪除

(2) 刪除關聯投稿信息
VideoInfoFilePostQuery videoInfoFilePostQuery = new VideoInfoFilePostQuery();
videoInfoFilePostQuery.setVideoId(videoId);
videoInfoFilePostMapper.deleteByParam(videoInfoFilePostQuery);

? 直接刪除:無需查詢,根據videoId直接刪除

(3) 刪除彈幕數據
VideoDanmuQuery videoDanmuQuery = new VideoDanmuQuery();
videoDanmuQuery.setVideoId(videoId);
videoDanmuMapper.deleteByParam(videoDanmuQuery);

? 批量刪除:通過videoId一次性刪除所有關聯彈幕

(4) 刪除評論數據
VideoCommentQuery videoCommentQuery = new VideoCommentQuery();
videoCommentQuery.setVideoId(videoId);
videoCommentMapper.deleteByParam(videoCommentQuery);

? 級聯刪除:通常需要確保評論的關聯數據(回復、點贊等)也被清理

(5) 物理文件刪除
for (VideoInfoFile item : videoInfoFileList) {try {FileUtils.deleteDirectory(new File(appConfig.getProjectFolder() + item.getFilePath()));} catch (IOException e) {log.error("刪除文件失敗,文件路徑:{}", item.getFilePath());}
}

? 關鍵點
? 使用deleteDirectory刪除整個目錄
? 捕獲并記錄IO異常,避免任務中斷
? 文件路徑拼接了項目基礎目錄(appConfig.getProjectFolder())

4. 異步設計的優缺點分析

優點
  1. 響應速度:主線程快速返回,用戶體驗好
  2. 資源隔離:IO密集型操作不影響核心業務
  3. 錯誤隔離:文件刪除失敗不影響主流程
缺點及風險
  1. 事務不一致

    // 主事務提交后異步任務才執行
    // 若異步任務失敗,系統處于不一致狀態
    
  2. 錯誤處理缺失

    // 當前實現沒有記錄任務執行結果
    // 無法知道異步操作是否成功
    
  3. 資源競爭

    // 固定10個線程可能在高并發時成為瓶頸
    // 文件刪除操作可能阻塞其他異步任務
    

5. 改進建議

(1) 增強型線程池配置
private static ExecutorService executorService = new ThreadPoolExecutor(5, // 核心線程數20, // 最大線程數60, TimeUnit.SECONDS, // 空閑線程存活時間new ArrayBlockingQueue<>(1000), // 有界隊列new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略
);
(2) 添加任務結果處理
Future<?> future = executorService.submit(() -> {// 任務代碼
});// 可選:通過Future跟蹤任務狀態
future.get(10, TimeUnit.SECONDS); // 帶超時的等待
(3) 事務補償機制
@TransactionalEventListener(phase = AFTER_COMMIT)
public void handleAfterCommit(VideoDeleteEvent event) {// 主事務提交后執行異步清理asyncCleanService.cleanVideoResources(event.getVideoId());
}
(4) 完善日志監控
executorService.execute(() -> {MDC.put("traceId", UUID.randomUUID().toString());try {// 任務代碼log.info("視頻資源清理完成: {}", videoId);} catch (Exception e) {log.error("視頻資源清理失敗: {}", videoId, e);// 發送告警或記錄失敗狀態} finally {MDC.clear();}
});

總結

這個刪除方法通過線程池實現了:

  1. 核心數據同步刪除:保證關鍵數據立即清除
  2. 資源異步清理:提升響應速度
  3. 物理文件刪除:釋放存儲空間

關鍵改進方向
? 線程池參數優化
? 完善錯誤處理和狀態跟蹤
? 考慮引入事務事件機制
? 增加監控和告警能力

這種設計適合對實時性要求高但允許最終一致性的場景,是典型的"快速響應+后臺清理"架構模式。

異步線程池及executorService.execute詳解

一、異步線程池基礎

1. 線程池核心概念

線程池是一種線程管理機制,它維護著多個線程,避免頻繁創建和銷毀線程帶來的性能開銷。在Java中,主要通過ExecutorService接口及其實現類來使用線程池。

2. 線程池關鍵參數

參數說明示例值
corePoolSize核心線程數10
maximumPoolSize最大線程數50
keepAliveTime空閑線程存活時間60秒
workQueue任務隊列new LinkedBlockingQueue(1000)
threadFactory線程創建工廠Executors.defaultThreadFactory()
handler拒絕策略AbortPolicy

3. 線程池工作流程

  1. 提交任務時,優先使用核心線程處理
  2. 核心線程全忙時,任務進入隊列
  3. 隊列滿時,創建新線程(不超過maxPoolSize)
  4. 線程數達最大值且隊列滿時,觸發拒絕策略

二、executorService.execute方法詳解

1. 方法簽名

void execute(Runnable command)

2. 核心特點

? 異步執行:立即返回,不阻塞調用線程
? 無返回值:適用于不需要獲取結果的場景
? 異常處理:任務異常會傳遞給未捕獲異常處理器

3. 執行流程

Caller Executor Queue Worker execute(task) 立即執行 放入隊列 隊列非空時取出執行 alt [有可用核心線程] [無可用核心線程] 任務完成 Caller Executor Queue Worker

4. 在示例代碼中的使用

executorService.execute(() -> {// 1. 查詢和刪除分P視頻VideoInfoFileQuery videoInfoFileQuery = new VideoInfoFileQuery();videoInfoFileQuery.setVideoId(videoId);List<VideoInfoFile> videoInfoFileList = this.videoInfoFileMapper.selectList(videoInfoFileQuery);videoInfoFileMapper.deleteByParam(videoInfoFileQuery);// 2. 刪除其他關聯數據...// 3. 刪除物理文件for (VideoInfoFile item : videoInfoFileList) {try {FileUtils.deleteDirectory(new File(appConfig.getProjectFolder() + item.getFilePath()));} catch (IOException e) {log.error("刪除文件失敗,文件路徑:{}", item.getFilePath());}}
});

5. 為什么使用execute而不是submit?

對比項executesubmit
返回值Future對象
異常處理直接拋出封裝在Future中
適用場景簡單異步任務需要獲取結果的任務
示例代碼當前場景適合需要結果時使用

在當前場景下:
? 不需要獲取清理操作的結果
? 簡單的日志記錄已足夠
? 更輕量級的執行方式

三、線程池配置優化建議

1. 當前實現的潛在問題

private static ExecutorService executorService = Executors.newFixedThreadPool(10);

? 使用無界隊列(默認LinkedBlockingQueue),可能導致OOM
? 固定線程數無法應對突發流量
? 缺少合理的拒絕策略

2. 推薦改進方案

private static ExecutorService executorService = new ThreadPoolExecutor(5,                              // 核心線程數20,                             // 最大線程數60, TimeUnit.SECONDS,           // 空閑線程存活時間new ArrayBlockingQueue<>(1000), // 有界隊列new ThreadPoolExecutor.CallerRunsPolicy() // 拒絕策略
);

3. 各參數說明

  1. corePoolSize=5:保持5個常駐線程
  2. maxPoolSize=20:突發流量時可擴展到20線程
  3. keepAliveTime=60s:空閑線程60秒后回收
  4. 有界隊列(1000):防止資源耗盡
  5. CallerRunsPolicy:隊列滿時由調用線程執行任務

四、異常處理機制

1. 當前實現的異常處理

try {FileUtils.deleteDirectory(...);
} catch (IOException e) {log.error("刪除文件失敗...");
}

? 僅記錄日志,無恢復機制
? 異常不會傳播到主線程

2. 增強型異常處理方案

方案1:全局異常處理器
executorService = new ThreadPoolExecutor(// ...其他參數new ThreadPoolExecutor.AbortPolicy() {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor e) {// 記錄被拒絕的任務log.warn("Task rejected: {}", r.toString());super.rejectedExecution(r, e);}}
);// 設置未捕獲異常處理器
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {log.error("Uncaught exception in thread: {}", t.getName(), e);
});
方案2:封裝任務
public class SafeRunnable implements Runnable {private final Runnable task;public SafeRunnable(Runnable task) {this.task = task;}@Overridepublic void run() {try {task.run();} catch (Exception e) {log.error("Task execution failed", e);// 可添加重試或補償邏輯}}
}// 使用方式
executorService.execute(new SafeRunnable(() -> {// 任務代碼
}));

五、性能監控建議

1. 添加線程池監控

// 定時打印線程池狀態
ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
monitor.scheduleAtFixedRate(() -> {ThreadPoolExecutor tpe = (ThreadPoolExecutor) executorService;log.info("Pool stats: active={}, queue={}/{}, completed={}",tpe.getActiveCount(),tpe.getQueue().size(),tpe.getQueue().remainingCapacity(),tpe.getCompletedTaskCount());
}, 1, 1, TimeUnit.MINUTES);

2. 關鍵監控指標

指標說明健康值參考
activeCount活動線程數< maxPoolSize
queueSize隊列大小< queueCapacity * 0.8
completedTaskCount已完成任務持續增長
rejectedCount被拒絕任務= 0

六、實際應用場景分析

1. 當前視頻刪除場景特點

? 耗時操作:文件刪除可能很慢
? 非關鍵路徑:不影響主業務流程
? 允許延遲:最終一致性即可
? 可能失敗:文件可能被占用等

2. 為什么適合使用線程池?

  1. 解耦:將清理操作與主業務分離
  2. 提速:主線程快速返回
  3. 可控:通過線程池限制資源使用
  4. 可擴展:方便添加重試等機制

3. 潛在風險及應對

風險應對措施
線程泄漏使用有界隊列,合理配置存活時間
任務丟失添加持久化隊列或任務記錄
資源競爭監控和動態調整線程池參數
異常傳播完善任務級別的異常處理

七、總結最佳實踐

  1. 選擇合適的線程池類型:根據場景選擇fixed/cached/custom
  2. 使用有界隊列:防止資源耗盡
  3. 配置合理的拒絕策略:如CallerRunsPolicy
  4. 完善異常處理:任務級別和全局級別
  5. 添加監控:實時了解線程池狀態
  6. 考慮任務重要性:關鍵任務建議使用帶返回值的submit

在視頻刪除場景中,通過線程池異步處理清理任務是一種合理的設計,但需要注意:
? 線程池參數的合理配置
? 異常情況的妥善處理
? 重要操作的日志記錄
? 系統資源的監控告警

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

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

相關文章

《比特信使的七重試煉:從數據丟失到CA認證的守護史詩》

點擊下面圖片帶您領略全新的嵌入式學習路線 &#x1f525;爆款熱榜 88萬閱讀 1.6萬收藏 第一章&#xff1a;初現危機——數據丟失的陰云 比特城的清晨總是被數據流的光芒點亮&#xff0c;但這一天&#xff0c;工程師艾琳的實驗室卻籠罩在陰霾中。她剛剛嘗試通過古老的“疾風…

如何更好的理解 beforeEach 全局前置守衛,在處理路由跳轉前觸發,怎么實現常用的全局權限校驗、登錄狀態檢查的呢?

以下將深入講解 Vue Router 的全局前置守衛 beforeEach 在權限系統中的實現原理和實戰應用&#xff0c;結合企業級項目代碼進行拆解&#xff08;基于 Vue 3 TypeScript Pinia&#xff09;。 一、前置守衛核心機制 1.1 執行時機與特性 全局前置守衛在路由跳轉前觸發&#xf…

VMware上的windows虛擬機安裝使用Docker方法

因為在實體機上使用Docker會導致VMware無法啟動虛擬機&#xff0c;所以嘗試了在虛擬機中安裝Docker. 1. 創建Windows虛擬機. windows至少是Win10 1.9***或者Win 11. 這是Docker Desktop要求的。 2. 虛擬機CPU要開啟虛擬化功能。 虛擬機的CPU開啟虛擬化 虛擬機的memory要不小…

項目中集成ECharts圖表(通過定時任務SpringTask統計每天的訂單金額)

項目應用Echarts ①、前端終端安裝Echarts npm install echarts --save ②、src/views創建order目錄&#xff0c;在order目錄下創建orderStatistics.vue ③、src/router/modules目錄下創建order.js&#xff0c;配置路由 const layout ()>import(/layout/index.vue) …

2022第十三屆藍橋杯大賽軟件賽省賽C/C++ 大學 B 組(題解解析)

記錄刷題的過程、感悟、題解。 希望能幫到&#xff0c;那些與我一同前行的&#xff0c;來自遠方的朋友&#x1f609; 大綱&#xff1a; 1、九進制轉十進制-&#xff08;解析&#xff09;-簡單的進制轉化問題&#x1f604; 2、順子日期-&#xff08;解析&#xff09;-考察日期 3…

python應用之使用pdfplumber 解析pdf文件內容

目錄標題 一. 通過 pdfplumber.open() 解析復雜PDF&#xff1a;1-2. 報錯&#xff1a;V2 &#xff1a; 1-3. v3 使用tk 庫&#xff0c;彈框選擇文件運行環境準備完整代碼保存運行測試步驟方式二&#xff1a;命令行方式&#xff08;適用于自動化&#xff09; 測試用例示例常見問…

力扣熱題100刷題day61|234.回文鏈表(兩種方法)

一、回文鏈表 234.回文鏈表 兩種解法 解法1&#xff1a;時間復雜度O(n) 空間復雜度O(n) 遍歷鏈表&#xff0c;計算鏈表長度&#xff0c;創建同樣長度大小的數組&#xff0c;用數組存儲鏈表中所有元素&#xff0c;之后雙指針遍歷鏈表&#xff0c;一個從頭開始&#xff0c;一…

vue3+element-plus動態與靜態表格數據渲染

一、表格組件&#xff1a; <template> <el-table ref"myTable" :data"tableData" :header-cell-style"headerCellStyle" header-row-class-name"my-table-header" cell-class-name"my-td-cell" :row-style"r…

Kafka 中的生產者分區策略

Kafka 中的 生產者分區策略 是決定消息如何分配到不同分區的機制。這個策略對 Kafka 的性能、負載均衡、消息順序性等有重要影響。了解它對于高效地使用 Kafka 進行消息生產和消費至關重要。 讓我們一起來看 Kafka 中 生產者的分區策略&#xff0c;它如何工作&#xff0c;以及…

《從零搭建Vue3項目實戰》(AI輔助搭建Vue3+ElemntPlus后臺管理項目)零基礎入門系列第二篇:項目創建和初始化

&#x1f91f;致敬讀者 &#x1f7e9;感謝閱讀&#x1f7e6;笑口常開&#x1f7ea;生日快樂?早點睡覺 &#x1f4d8;博主相關 &#x1f7e7;博主信息&#x1f7e8;博客首頁&#x1f7eb;專欄推薦&#x1f7e5;活動信息 文章目錄 《從零搭建Vue3項目實戰》&#xff08;AI輔助…

全國產FMC子卡-16bit 8通道2.4G

國產化FMC DA子卡&#xff0c;16bit 8通道2.4GS/s 全國產FMC子卡是一款高分辨率、高采樣率的全國產多通道標準雙寬DAC FMC子板。其接口電氣和結構設計均依據FMC標準(ANSI/VITA 57.1)&#xff0c;通過兩個高密度FMC連接器&#xff08;HPC&#xff09;連接至FPGA載板。它提供8路A…

linux-添加開機自啟動指定腳本

一、systemd 服務&#xff08;主流方法&#xff09; 適用于使用systemd的現代發行版&#xff08;Ubuntu 16.04/CentOS 7&#xff09; 創建服務文件 sudo nano /etc/systemd/system/your_script.service寫入服務配置&#xff08;示例&#xff09;&#xff1a; [Unit] Descri…

Spring MVC 返回 JSON 視圖的方式及對比(6種)

Spring MVC 返回 JSON 視圖的方式及對比&#xff08;新增 MappingJackson2JsonView&#xff09; 1. 方式一&#xff1a;ResponseBody 注解 作用&#xff1a;直接返回對象&#xff0c;由消息轉換器&#xff08;如 Jackson&#xff09;序列化為 JSON。 適用場景&#xff1a;簡單…

瑞芯微RK3568嵌入式AI項目實戰:智能家居項目(二)

RK3568智能家居項目實戰指南&#xff1a;從入門到精通的完整制作流程 瑞芯微RK3568作為一款高性能嵌入式處理器&#xff0c;憑借其四核Cortex-A55架構、1T算力NPU和豐富的外設接口&#xff0c;成為智能家居項目開發的理想平臺。下面我將推薦幾個典型的RK3568智能家居項目&…

GStreamer開發筆記(一):GStreamer介紹,在windows平臺部署安裝,打開usb攝像頭對比測試

若該文為原創文章&#xff0c;轉載請注明原文出處 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/147049923 長沙紅胖子Qt&#xff08;長沙創微智科&#xff09;博文大全&#xff1a;開發技術集合&#xff08;包含Qt實用技術、樹莓派、三維、O…

Spring Boot 3.4.3 和 Spring Security 6.4.2 實現基于內存和 MySQL 的用戶認證

在 Web 應用開發中&#xff0c;用戶認證是保障系統安全的基礎需求。Spring Boot 3.4.3 結合 Spring Security 6.4.2 提供了強大的安全框架支持&#xff0c;可以輕松實現基于內存或數據庫的用戶認證功能。本文將詳細介紹如何在 Spring Boot 3.4.3 中集成 Spring Security 6.4.2&…

HOW - Axios 攔截器特性

目錄 Axios 介紹攔截器特性1. 統一添加 Token&#xff08;請求攔截器&#xff09;2. 處理 401 未授權&#xff08;響應攔截器&#xff09;3. 統一處理錯誤信息&#xff08;響應攔截器&#xff09;4. 請求 Loading 狀態管理5. 自動重試請求&#xff08;如 429 過載&#xff09;6…

JVM核心機制:類加載×字節碼引擎×垃圾回收機制

&#x1f680;前言 “為什么你的Spring應用啟動慢&#xff1f;為什么GC總是突然卡頓&#xff1f;答案藏在JVM的核心機制里&#xff01; 本文將用全流程圖解字節碼案例&#xff0c;帶你穿透三大核心機制&#xff1a; 類加載&#xff1a;雙親委派如何防止惡意代碼入侵&#xff…

coze生成流程圖和思維導圖工作流

需求&#xff1a;通過coze平臺實現生成流程圖和思維導圖&#xff0c;要求支持文檔上傳 最終工作流如下&#xff1a; 入參&#xff1a; 整合用戶需求文件內容的工作流&#xff1a;https://blog.csdn.net/YXWik/article/details/147040071 選擇器分發&#xff0c;不同的類型走…

網絡安全應急響應-文件痕跡排查

在Windows系統的網絡安全應急響應中&#xff0c;文件痕跡排查是識別攻擊行為的關鍵步驟。以下是針對敏感目錄的詳細排查指南及擴展建議&#xff1a; 1. 臨時目錄排查&#xff08;Temp/Tmp&#xff09; 路徑示例&#xff1a; C:\Windows\TempC:\Users\<用戶名>\AppData\L…