for循環(huán)內線程池并發(fā)執(zhí)行任務,等到子線程全部處理完任務,主線程在執(zhí)行
方式一 使用 CountDownLatch
在 Java 中,您可以使用 CountDownLatch 來實現主線程等待子線程執(zhí)行完成的功能。CountDownLatch 是一個同步工具類,它允許一個或多個線程等待其他線程完成操作后再繼續(xù)執(zhí)行。
具體來說,您可以在每個子線程中創(chuàng)建一個 CountDownLatch 對象,并將計數器初始化為 1。當子線程處理完任務后,調用 CountDownLatch.countDown() 方法,將計數器減 1。在主線程中,調用 CountDownLatch.await() 方法阻塞等待所有子線程的任務執(zhí)行完畢,直到計數器減為 0 才繼續(xù)執(zhí)行后續(xù)代碼。
以下是一個簡單的示例代碼:
ExecutorService executor = Executors.newFixedThreadPool(5); // 創(chuàng)建擁有 5 個線程的線程池
CountDownLatch latch = new CountDownLatch(5); // 創(chuàng)建計數器,初始值為 5
for (int i = 0; i < 5; i++) {
executor.submit(() -> {
// 子線程處理任務
doTask();
latch.countDown(); // 計數器減 1
});
}
try {
latch.await(); // 等待所有子線程的任務執(zhí)行完畢
} catch (InterruptedException e) {
// 處理中斷異常
}
// 所有子線程的任務都已經執(zhí)行完畢,執(zhí)行主線程的代碼
doSomethingElse();
請注意,在實際應用中,您還需要考慮線程安全、并發(fā)訪問等問題,并在代碼中正確處理異常。例如,在子線程處理任務時,可能需要使用鎖或其他同步機制來保護共享資源的訪問;在主線程等待子線程執(zhí)行完畢時,可能需要處理 InterruptedException 異常等異常情況。
方式二 使用 ExecutorService 的 invokeAll() 方法
如果您不想使用 CountDownLatch,還有其他方法可以實現主線程等待子線程任務執(zhí)行完畢的功能。以下是一些常見的方式:
使用 ExecutorService 的 invokeAll() 方法
ExecutorService 中的 invokeAll() 方法可以提交多個 Callable 或 Runnable 任務,并阻塞等待所有任務完成。該方法返回一個 Future 對象列表,可以通過遍歷列表獲取各個子線程處理任務后的結果。
以下是一個使用 invokeAll() 方法的示例代碼
ExecutorService executor = Executors.newFixedThreadPool(5); // 創(chuàng)建擁有 5 個線程的線程池
List<Callable<Void>> tasks = new ArrayList<>();
for (int i = 0; i < 5; i++) {
tasks.add(() -> {
// 子線程處理任務
doTask();
return null;
});
}
executor.invokeAll(tasks); // 等待所有子線程的任務執(zhí)行完畢
// 所有子線程的任務都已經執(zhí)行完畢,執(zhí)行主線程的代碼
doSomethingElse();
方式三 使用 CompletableFuture 的 allOf() 方法
Java 8 中引入了 CompletableFuture 類,它提供了一系列基于回調函數的異步編程方法,可以方便地實現多線程任務的并發(fā)執(zhí)行和結果組合。其中,allOf() 方法可以用于等待所有 CompletableFuture 對象的計算結果。
以下是一個使用 CompletableFuture 的 allOf() 方法的示例代碼:
ExecutorService executor = Executors.newFixedThreadPool(5); // 創(chuàng)建擁有 5 個線程的線程池
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < 5; i++) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
// 子線程處理任務
doTask();
}, executor);
futures.add(future);
}
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); // 等待所有子線程的任務執(zhí)行完畢
// 所有子線程的任務都已經執(zhí)行完畢,執(zhí)行主線程的代碼
doSomethingElse();
請注意,在使用以上方法時,仍然需要考慮線程安全、并發(fā)訪問等問題,并在代碼中正確處理異常。
方式四
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // corePoolSize
5, // maximumPoolSize
0L, TimeUnit.MILLISECONDS, // keepAliveTime, unit
new LinkedBlockingQueue<Runnable>()); // workQueue
AtomicInteger count = new AtomicInteger(5); // 計數器,初始值為 5
for (int i = 0; i < 5; i++) {
executor.execute(() -> {
// 子線程處理任務
doTask();
count.decrementAndGet(); // 計數器減 1
});
}
while (count.get() > 0) {
Thread.sleep(100); // 等待一段時間,避免空轉浪費 CPU 資源
}
// 所有子線程的任務都已經執(zhí)行完畢,執(zhí)行主線程的代碼
doSomethingElse();
在上述代碼中,我們創(chuàng)建了一個 ThreadPoolExecutor 對象,然后通過 AtomicInteger 實現了一個計數器,初始值為 5。在每個子線程執(zhí)行完任務后,計數器的值減 1。在主線程中使用 while 循環(huán)檢查計數器是否為 0,如果未達到目標,則阻塞等待一段時間,避免空轉浪費 CPU 資源。當計數器減為 0 時,所有子線程的任務都已經執(zhí)行完畢,主線程可以執(zhí)行后續(xù)代碼。文章來源:http://www.zghlxwxcb.cn/news/detail-672504.html
請注意,在使用自定義線程池時,需要考慮線程安全、并發(fā)訪問等問題,并在代碼中正確處理異常。例如,在子線程處理任務時,可能需要使用鎖或其他同步機制來保護共享資源的訪問;在主線程等待子線程執(zhí)行完畢時,可能需要處理 InterruptedException 異常等異常情況。文章來源地址http://www.zghlxwxcb.cn/news/detail-672504.html
到了這里,關于for循環(huán)內線程池并發(fā)執(zhí)行任務,等到子線程全部處理完任務,主線程在執(zhí)行java的實現方式的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!