java阻塞主线程等待多个子线程执行完毕的解决方案

您所在的位置:网站首页 等待线程池里的线程全部执行完任务怎么办 java阻塞主线程等待多个子线程执行完毕的解决方案

java阻塞主线程等待多个子线程执行完毕的解决方案

2024-07-12 04:27| 来源: 网络整理| 查看: 265

问题:

采用while(true)方式阻塞主线程,等待多个子线程执行完毕的方案。在系统负载升高时,存在while循环占用过多时间片,导致CPU被打满风险。

问题代码示例:

final long start = System.currentTimeMillis(); while (true) { if (System.currentTimeMillis() - start >= 5 * MilliSecond.SECOND) { break; } if (futureList.parallelStream().allMatch(Future::isDone)) { break; } } /** * 等待全部线程完成(超时时间30s) * @param futureList List:future中装载线程内抛出的异常,线程正常结束则需要装载null */ public static void waitComplete(List futureList) throws Exception { final long start = System.currentTimeMillis(); while (true) { if (System.currentTimeMillis() - start >= 30 * MilliSecond.SECOND) { break; } if (futureList.stream().allMatch(Future::isDone)) { for (Future future : futureList) { if (future.get() != null) { throw future.get(); } } break; } } }

解决方案:

建议使用java8提供的CompletableFuture,配合allof和join方法,阻塞主线程。

完整示例代码如下:

package com.mark.utils.thread; import org.apache.commons.collections.CollectionUtils; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; /** * 线程相关工具类 * @author mark * @date 2022/9/8 10:58 */ @Component public class ThreadUtils { @Resource private ThreadPoolTaskExecutor commonTaskExecutor; @Resource private ThreadPoolTaskExecutor expensiveTaskExecutor; /** * 使用commonTaskExecutor线程池,开启新线程执行异步任务,新线程无返回值 */ public CompletableFuture commonTaskExecutorRun(Runnable runnable) { return CompletableFuture.runAsync(runnable, commonTaskExecutor); } /** * 使用commonTaskExecutor线程池,开启新线程执行异步任务,新线程有返回值 */ public CompletableFuture commonTaskExecutorSupply(Supplier supplier) { return CompletableFuture.supplyAsync(supplier, commonTaskExecutor); } /** * 使用expensiveTaskExecutor线程池,开启新线程执行异步任务,新线程无返回值 */ public CompletableFuture expensiveTaskExecutorRun(Runnable runnable) { return CompletableFuture.runAsync(runnable, expensiveTaskExecutor); } /** * 使用expensiveTaskExecutor线程池,开启新线程执行异步任务,新线程有返回值 */ public CompletableFuture expensiveTaskExecutorSupply(Supplier supplier) { return CompletableFuture.supplyAsync(supplier, expensiveTaskExecutor); } /** * 阻塞主线程,等待全部future执行完毕 */ public static void waitComplete(List futureList) { if (CollectionUtils.isEmpty(futureList)) { return; } CompletableFuture .allOf(futureList.toArray(new CompletableFuture[0])) .join(); } /** * 阻塞主线程,等待全部future执行完毕,线程返回的异常会被抛出 * @param futureList List:future中装载线程内抛出的异常,线程正常结束则需要装载null */ public static void waitCompleteThrow(List futureList) throws Exception { waitComplete(futureList); for (CompletableFuture future : futureList) { if (future.get() != null) { throw future.get(); } } } }

CompletableFuture API:

runAsync(Runnable runnable, Executor executor)

返回一个新的不携带返回值的CompletableFuture,使用指定的线程池执行任务。

supplyAsync(Supplier supplier, Executor executor)

返回一个新的携带返回值的CompletableFuture,使用指定的线程池执行任务。

allOf(CompletableFuture… cfs)

返回一个新的CompletableFuture,当入参中所有CompletableFuture都执行完成后,它也会执行完成。

多个CompletableFuture独立执行,某个CompletableFuture抛出异常不会干扰其他。

get() throw InterruptedException, ExecutionException

阻塞当前线程,直到全部CompletableFuture执行完成,并拿到执行结果。

CompletableFuture执行过程中的异常会被抛出,进而结束掉主线程。此外,多个异常只有一个会被抛出。

该方法抛出checked异常。

join()

阻塞当前线程,直到全部CompletableFuture执行完成,并拿到执行结果。CompletableFuture执行过程中的异常会被抛出,进而结束掉主线程。此外,多个异常只有一个会被抛出。该方法返回unchecked异常,这是该方法和get()方法的主要区别。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3