嵌套线程并发控制

场景:并发处理任务时,任务总数远大于线程池最大线程数,并且每一个任务内部还有并发处理的子任务,这种情况下,很容易导致线程死锁的情况,原因相信大家都清楚。故开发了该工具类。其中优缺点也很明显,但在业务处理中很实用。望大家多提提意见,完善该工具类。

/**
 * @Description: 
 * @Author: huyk
 * @CreateTime: 2023-12-06 11:27
 */
@Slf4j
public class ThreadUtil {

	static {
		executorService = ThreadPool.COMMON_POOL;
	}
	private static ExecutorService executorService;
	private String groupId;
	private CountDownLatch countDownLatch;

	private ThreadUtil (@NonNull String groupId, int taskCount) {
		ThreadPool.THREAD_GROUP_MAP.putIfAbsent(groupId,new ArrayBlockingQueue<>(ThreadPool.SINGLE_GROUP_TASK_THRESHOLD));
		this.groupId = groupId;
		this.countDownLatch = new CountDownLatch(taskCount);
	}

	public static ThreadUtil createLimiter(@NonNull String groupId, int taskCount){
		return new ThreadUtil (groupId,taskCount);
	}

	public ThreadUtil subTask(@NonNull Runnable runnable){
		ArrayBlockingQueue<ITask> subTaskQueue = ThreadPool.THREAD_GROUP_MAP.get(groupId);
		ITask iTask = new ITask(groupId,runnable,countDownLatch);
		try {
			subTaskQueue.put(iTask);
		}
		catch (InterruptedException ie) {
			log.error("[Thread-Limiter:subTask] InterruptedException:",ie);
		}
		boolean subSuccess = false;
		do {
			try{
				CompletableFuture.runAsync(iTask,executorService);
				subSuccess = true;
			}
			catch (RejectedExecutionException re){
				rejectedExecutionSleep();
				log.error("[Thread-Limiter:subTask] RejectedExecutionException:",re);
			}
		}
		while (!subSuccess);
		return this;
	}

	public void await(){
		try {
			countDownLatch.await();
		}
		catch (InterruptedException e) {
			log.error("[Thread-Limiter:await] InterruptedException:", e);
		}
	}

	private static void rejectedExecutionSleep(){
		try {
			Thread.sleep(ThreadPool.FAIL_PERIOD_MS);
		}
		catch (InterruptedException e) {
			log.error("[Thread-Limiter:RejectedExecutionSleep] InterruptedException:",e);
		}
	}

	private static class ITask implements Runnable{
		private Runnable task;
		private ArrayBlockingQueue<ITask> subTaskQueue;
		private CountDownLatch countDownLatch;

		public ITask(String groupId,
					 Runnable task,
					 CountDownLatch countDownLatch) {
			this.task = task;
			this.countDownLatch = countDownLatch;
			this.subTaskQueue = ThreadPool.THREAD_GROUP_MAP.get(groupId);
		}

		@Override
		public void run() {
			try{
				task.run();
			}
			catch (Exception e){
				log.error("[Thread-Limiter:ITask] task.run():", e);
			}
			finally {
				subTaskQueue.poll();
				countDownLatch.countDown();
			}
		}
	}	

	public static void runAsyncAndGet(@NonNull Runnable... runnables){
		runAsyncAndGet(Arrays.asList(runnables));
	}

	public static void runAsyncAndGet(@NonNull List<Runnable> runnableList){
		CompletableFuture[] completableFutures = runAsync(executorService, runnableList);
		if(null != completableFutures){
			try {
				CompletableFuture.allOf(completableFutures).get();
			}
			catch (Exception e) {
				log.error("[Thread-Limiter:runAsyncAndGet] error:", e);
			}
		}
	}

	public static CompletableFuture[] runAsync(@NonNull ExecutorService executor, @NonNull Runnable... runnables){
		return runAsync(executor,Arrays.asList(runnables));
	}

	public static CompletableFuture[] runAsync(@NonNull ExecutorService executor, @NonNull List<Runnable> runnableList){
		if(CollectionUtil.isNotEmpty(runnableList)){
			CompletableFuture[] completableFutures = new CompletableFuture[runnableList.size()];
			for (int i = 0; i < runnableList.size(); i++) {
				boolean exeSuccess = false;
				do {
					try {
						completableFutures[i] = CompletableFuture.runAsync(runnableList.get(i), executor);
						exeSuccess = true;
					}
					catch (RejectedExecutionException re){
						rejectedExecutionSleep();
						log.error("[Thread-Limiter:runAsync] RejectedExecutionException:", re);
					}
				}
				while (!exeSuccess);
			}
			return completableFutures;
		}
		return null;
	}

	private static class ThreadPool{
		private static final String NEW_NAMED_THREAD_PREFIX = "wms-pool-thread-";
		private static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
		private static final int CORE_POOL_SIZE = AVAILABLE_PROCESSORS;
		private static final int MAX_POOL_SIZE = CORE_POOL_SIZE + 5;
		private static final int SINGLE_GROUP_TASK_THRESHOLD = CORE_POOL_SIZE * 2 / 5;
		private static final long FAIL_PERIOD_MS = 20;
		private static final ExecutorService COMMON_POOL =
				ExecutorBuilder.create().setCorePoolSize(AVAILABLE_PROCESSORS)
						.setMaxPoolSize(MAX_POOL_SIZE)
						.setThreadFactory(ThreadUtil.newNamedThreadFactory(NEW_NAMED_THREAD_PREFIX, Boolean.FALSE))
						.useSynchronousQueue()
						.build();
		private static final ConcurrentHashMap<String, ArrayBlockingQueue<ITask>> THREAD_GROUP_MAP = new ConcurrentHashMap<>();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值