java?for循環(huán)內(nèi)執(zhí)行多線程問題
java用多線程來加快循環(huán)效率
線程池搭配閉鎖
涉及知識:Executors(線程池)、CountDownLatch(閉鎖)
優(yōu)點:代碼簡潔,方便閱讀,性能穩(wěn)定;
缺點:Executors創(chuàng)建的線程池是公用的,如果多個地方使用這種循環(huán)多線程的方式,就會搶奪線程池資源,這樣運行速度也會降低;
import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class test{ /** 固定的線程池(當前線程池大小為5) */ private static final ExecutorService executor = Executors.newFixedThreadPool(5); public static void main(String[] args) throws Exception { /** * 兩個要點: * 1.用Executors實現(xiàn)固定大小的線程池,從而達到控制硬件資源消耗的目的。 * 2.用CountDownLatch(閉鎖),來確保循環(huán)內(nèi)的多線程都執(zhí)行完成后,再執(zhí)行后續(xù)代碼 */ // 初始化數(shù)據(jù) List<Map<String,Object>> list = new ArrayList<>(); for(int i=0;i<50;i++){ Map<String,Object> object = new HashMap<>(); object.put("index",i); list.add(object); } // 初始化計時器 CountDownLatch cdl = new CountDownLatch(list.size()); System.out.println("====== 線程開始 ====="); // 遍歷 for(Map<String,Object> object:list){ // 開啟線程 executor.submit(new Runnable() { @Override public void run() { try { Thread t = Thread.currentThread(); String name = t.getName(); // 模擬運行耗時 Thread.sleep(500); System.out.println(name+":執(zhí)行到"+object.get("index")); object.put("status","已經(jīng)執(zhí)行過"); } catch (InterruptedException e) { e.printStackTrace(); } // 閉鎖-1 cdl.countDown(); } }); } // 調(diào)用閉鎖的await()方法,該線程會被掛起,它會等待直到count值為0才繼續(xù)執(zhí)行 // 這樣我們就能確保上面多線程都執(zhí)行完了才走后續(xù)代碼 cdl.await(); //關(guān)閉線程池 executor.shutdown(); System.out.println("====== 線程結(jié)束 ====="); // 校驗多線程正確性 for(Map<String,Object> object:list){ System.out.println(object.get("index") + ":" + object.get("status")); } } }
for循環(huán)中使用多線程
每個service負責一個業(yè)務(wù),多次進行重復(fù)業(yè)務(wù)就要使用到for循環(huán),例如對某個存儲id的集合遍歷,并為每個id創(chuàng)建一些東西。
但是使用單線程執(zhí)行任務(wù)會因為等待上次任務(wù)執(zhí)行完而浪費很多時間,并且一旦某次執(zhí)行報錯,任務(wù)就會停止執(zhí)行,明顯不符合我們的要求。
這種情況就在for循環(huán)中使用多線程。
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; public class Test { /** * ThreadPool 自定義一個線程池 */ private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(60000)); public static void main(String[] args) { //自己的數(shù)組或集合,這里不再進行填充 String[] ids = new String[10] for (String id : ids) { EXECUTOR.execute(new Runnable() { @Override public void run() { try { //需要執(zhí)行的業(yè)務(wù)邏輯 System.out.println("業(yè)務(wù)邏輯正在執(zhí)行"); } catch (Exception e) { //todo } } }); } } }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot環(huán)境Druid數(shù)據(jù)源使用及特點
Druid 是目前比較流行的高性能的,分布式列存儲的OLAP框架(具體來說是MOLAP)。本文給大家分享SpringBoot環(huán)境Druid數(shù)據(jù)源使用及特點介紹,感興趣的朋友跟隨小編一起看看吧2021-07-07SpringBoot實現(xiàn)OneDrive文件上傳的詳細步驟
這篇文章主要介紹了SpringBoot實現(xiàn)OneDrive文件上傳的詳細步驟,文中通過代碼示例和圖文講解的非常詳細,對大家實現(xiàn)OneDrive文件上傳有一定的幫助,需要的朋友可以參考下2024-02-02帶你走進Maven的大門-最全Maven配置及集成idea工具總結(jié)
Maven項目對象模型(POM),是一個項目管理工具可以通過一小段描述信息來管理項目的構(gòu)建,報告和文檔的軟件.那我們想要在IDEA中使用Maven得進行一些配置,接下來我們具體看一下是如何配置使用的,需要的朋友可以參考下2021-06-06SpringBoot整合Caffeine實現(xiàn)本地緩存的實踐分享
緩存是提升系統(tǒng)性能的一個不可或缺的工具,通過緩存可以避免大部分重復(fù)的請求到數(shù)據(jù)庫層,減少IO鏈接次數(shù),提升整體的響應(yīng)速率,本地緩存中比較常見的比如 Caffeine 緩存,這篇文章將結(jié)合具體的 Springboot 項目搭配 Caffeine 實現(xiàn)本地緩存的各種使用方式2024-07-07Spring?Security過濾器鏈加載執(zhí)行流程源碼解析
Spring?Boot?對于?Spring?Security?提供了自動化配置方案,可以使用更少的配置來使用?Spring?Security。那么這個過濾器鏈是怎么加載和實現(xiàn)攔截的呢,對Spring?Security過濾器鏈加載執(zhí)行流程感興趣的朋友一起看看吧2021-12-12