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

