java多线程分批执行任务demo

一、需求描述

利用线程池实现多线程分批执行任务。

例如:线程池容量为10,我有20个任务,第一次利用线程池中的10个线程异步执行完10个任务。10个任务完成后,不管任务成功或者失败,线程池回收10个线程继续完成剩下10个任务。

实际应用:当我们批量的需求比如启动1000个节点,启动一个节点的时间大概是3s,我们肯定不会去并行执行1000次启动,肯定是利用线程池的技术利用多线去异步启动1000个节点,但是我们又不可能给线程池1000个线程去准备,只能采用循环分批的思想去执行1000次启动。

二、代码示例

主函数:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.google.common.collect.Lists;

public class BatchTest2 {
	public static void main(String[] args) throws InterruptedException {
		//线程池10个线程
		ExecutorService executorService = Executors.newFixedThreadPool(10);
		//第一批十个任务
		List<StartAgent> agentsStart = Lists.newArrayList(new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent());
		//第二批十个任务
		List<StartAgent> agentsStart2 = Lists.newArrayList(new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent(),new StartAgent());
		List<List<StartAgent>> task = new ArrayList<>();
		task.add(agentsStart);
		task.add(agentsStart2);
		//记录任务执行时间
		long t1 = System.currentTimeMillis();
		CountDownLatch c ;
		//循环任务组
		for(List<StartAgent> startList : task){
			//定义线程阻塞为10
			c = new CountDownLatch(10);
			for(StartAgent agent : startList){
				agent.setCountDownLatch(c);
				executorService.submit(agent);
			}
			//阻塞,等待十个任务都执行后,才继续下一批10任务
			c.await();
		}
		long t2 = System.currentTimeMillis();
		System.out.println("执行时间:"+  (t2 - t1)/1000);
		executorService.shutdown();
	}
}

StartAgent.java

import java.util.concurrent.CountDownLatch;

public class StartAgent implements Runnable {

	private CountDownLatch countDownLatch;

	@Override
	public void run() {
		try {
			System.out.println("开始启动节点:" + Thread.currentThread().getName());
			//模拟每个任务执行3秒钟
			Thread.sleep(3000);
			System.out.println(Thread.currentThread().getName() + "执行完毕");
			// 模拟执行任务异常
			// if(Thread.currentThread().getName().equals("pool-1-thread-4")){
			// System.out.println();
			// throw new InterruptedException("pool-1-thread-4启动失败");
			// }
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			//注意一定要在finally调用countDown,否则产生异常导致没调用到countDown造成程序死锁
			countDownLatch.countDown();
		}
	}

	public void setCountDownLatch(CountDownLatch countDownLatch) {
		this.countDownLatch = countDownLatch;
	}

}

三、调用结果

开始启动节点:pool-1-thread-1
开始启动节点:pool-1-thread-3
开始启动节点:pool-1-thread-5
开始启动节点:pool-1-thread-2
开始启动节点:pool-1-thread-6
开始启动节点:pool-1-thread-7
开始启动节点:pool-1-thread-4
开始启动节点:pool-1-thread-8
开始启动节点:pool-1-thread-9
开始启动节点:pool-1-thread-10
pool-1-thread-3执行完毕
pool-1-thread-1执行完毕
pool-1-thread-8执行完毕
pool-1-thread-9执行完毕
pool-1-thread-2执行完毕
pool-1-thread-5执行完毕
pool-1-thread-7执行完毕
pool-1-thread-4执行完毕
pool-1-thread-10执行完毕
pool-1-thread-6执行完毕
开始启动节点:pool-1-thread-3
开始启动节点:pool-1-thread-9
开始启动节点:pool-1-thread-2
开始启动节点:pool-1-thread-8
开始启动节点:pool-1-thread-1
开始启动节点:pool-1-thread-7
开始启动节点:pool-1-thread-10
开始启动节点:pool-1-thread-6
开始启动节点:pool-1-thread-5
开始启动节点:pool-1-thread-4
pool-1-thread-9执行完毕
pool-1-thread-2执行完毕
pool-1-thread-3执行完毕
pool-1-thread-8执行完毕
pool-1-thread-7执行完毕
pool-1-thread-1执行完毕
pool-1-thread-10执行完毕
pool-1-thread-5执行完毕
pool-1-thread-6执行完毕
pool-1-thread-4执行完毕
执行时间:6

可以看到,线程池先执行完第一批任务后,才执行第二批任务,而且每批任务都是异步执行,只用了3s,两批任务只用了6s。

以上只是一个简单的demo,提供一个思路,主要用到的知识点是CountDownLatch,网上对这个知识点介绍比较多了,我就不啰嗦了。

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值