使用CountDownLatch类作为信号枪,首先把大任务拆分成若干个小任务,类似于分页limit(0,1000),
然后计算一共要执行多少次.搞一个线程池,然后让线程池去执行这些任务,在执行任务前,先定义CountDownLatch的计数器有多少(一共要执行多少次),在一个线程执行完一段任务后,执行countDown()方法,计数器对应减1,然后在主线程中定义await()方法,当计数器减为0时,就自动执行主线程下面的逻辑.
public class Test02 {
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(5);
//假设我现在就有100000个任务 --》希望把这10000个任务拆分成若干个小任务,搞一个线程池,然后线程池 去执行这些任务
// 我们要先拆分成若干个小任务 ---> 类似于分页得那个效果 --> limit(0,1000) limit(1000,2000)
//当你把这个分页处理了好了之后,判断一下,这些任务一定要做多少 100次 -->100次循环走完之后,而且我可以把 分页得任务通过参数给他变化起来
int pageSize = 10;
int allCount = 100;
int page = allCount % pageSize == 0 ? allCount / pageSize : allCount / pageSize + 1;
CountDownLatch cdl = new CountDownLatch(page);
for (int i = 1; i <= page; i++) { // 1 2 3
//只要循环走完,我这10001 条记录全部都处理好了
threadPool.submit(new TaskThread(i, pageSize,cdl));
}
try {
// 主线程跑过去了,我再给他信号抢,只有当他听到信号枪之后,再往下边走
// 而且信号枪什么时候响起来呢,当所有分线程都跑完的时候,当这个变量没有变为0之前,他就会阻塞
cdl.await();
} catch (Exception e) {
e.printStackTrace();
}
}
static class TaskThread implements Runnable {
int page;
int pageSize;
CountDownLatch countDownLatch;
public TaskThread(int page, int pageSize,CountDownLatch countDownLatch) {
this.page = page;
this.pageSize = pageSize;
this.countDownLatch = countDownLatch;
}
// 想办法 0 1000:执行 0-999
// 想办法:1 1000 执行 1000-1999
// 想办法:2 1000执行 2000-2999
// ....
//当所有的循环都处理好之后,实际上所有的任务都完了
@Override
public void run() {
int startPage = (page-1)*pageSize; // 1 1000
int endPage = (page * pageSize) -1 ; // 999 1999
for (int i = startPage; i <= endPage; i++) {
System.out.println(Thread.currentThread().getName() + "正在处理第" + i );
}
countDownLatch.countDown();
}
}
}
值得一提的是: 如果是操作数据库的任务,持久层的mapper/Repository可以通过构造器传参 传过去,并且CountDownLatch一定是要传到任务中的,要保证信号枪次数的唯一