有时,为了程序的性能,我们有必要对程序中的for循环(含有sql/rpc操作)进行并发处理,要求是并发处理完之后才能继续执行主线程。现给出如下两种方案:

1. CountDownLatch

Java代码  
  1. package com.itlong.whatsmars.base.sync;
  2. import java.util.concurrent.CountDownLatch;
  3. /**
  4. * Created by shenhongxi on 2016/8/12.
  5. */
  6. public class CountDownLatchTest {
  7. public static void main(String[] args) {
  8. CountDownLatch latch = new CountDownLatch(3);
  9. long start = System.currentTimeMillis();
  10. for (int i = 0; i < 3; i++) {
  11. new Thread(new SubRunnable(i, latch)).start();
  12. }
  13. try {
  14. latch.await();
  15. } catch (InterruptedException e) {
  16. e.printStackTrace();
  17. }
  18. System.out.println(System.currentTimeMillis() - start);
  19. System.out.println("Main finished");
  20. }
  21. static class SubRunnable implements Runnable {
  22. private int id = -1;
  23. private CountDownLatch latch;
  24. SubRunnable(int id, CountDownLatch latch) {
  25. this.id = id;
  26. this.latch = latch;
  27. }
  28. @Override
  29. public void run() {
  30. try {
  31. Thread.sleep(3000);
  32. System.out.println(String
  33. .format("Sub Thread %d finished", id));
  34. } catch (InterruptedException e) {
  35. e.printStackTrace();
  36. } finally {
  37. latch.countDown();
  38. }
  39. }
  40. }
  41. }

CountDownLatch用队列来存放任务,主要是一个构造器和两个方法,相关代码这里不予赘述。CountDownLatch很贴合我们的要求,但没用到线程池,而且latch是只提供了计数功能然后子线程的逻辑有没有可能会在主线程逻辑之后执行??,综合考虑,我推荐下面的这种方案。

2. ExecutorService

Java代码  
  1. package com.itlong.whatsmars.base.sync;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.concurrent.Callable;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7. /**
  8. * Created by shenhongxi on 2016/8/12.
  9. */
  10. public class CallableTest {
  11. public static void main(String[] args) throws Exception {
  12. ExecutorService pool = Executors.newFixedThreadPool(3);
  13. List<Callable<Void>> subs = new ArrayList<Callable<Void>>();
  14. for (int i = 0; i < 3; i++) {
  15. subs.add(new SubCallable(i));
  16. }
  17. long start = System.currentTimeMillis();
  18. try {
  19. pool.invokeAll(subs);
  20. } finally {
  21. pool.shutdown();
  22. }
  23. System.out.println(System.currentTimeMillis() - start);
  24. System.out.println("Main finished");
  25. }
  26. static class SubCallable implements Callable<Void> {
  27. private int id = -1;
  28. public SubCallable(int id) {
  29. this.id = id;
  30. }
  31. @Override
  32. public Void call() throws Exception {
  33. try {
  34. Thread.sleep(3000);
  35. System.out.println(String
  36. .format("Child Thread %d finished", id));
  37. } catch (InterruptedException e) {
  38. e.printStackTrace();
  39. }
  40. return null;
  41. }
  42. }
  43. }

AbstractExecutorService

Java代码  
  1. public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
  2. throws InterruptedException {
  3. if (tasks == null)
  4. throw new NullPointerException();
  5. List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
  6. boolean done = false;
  7. try {
  8. for (Callable<T> t : tasks) {
  9. RunnableFuture<T> f = newTaskFor(t);
  10. futures.add(f);
  11. execute(f);
  12. }
  13. for (Future<T> f : futures) {
  14. if (!f.isDone()) {
  15. try {
  16. f.get();
  17. } catch (CancellationException ignore) {
  18. } catch (ExecutionException ignore) {
  19. }
  20. }
  21. }
  22. done = true;
  23. return futures;
  24. } finally {
  25. if (!done)
  26. for (Future<T> f : futures)
  27. f.cancel(true);
  28. }
  29. }

接下来我做了个join的试验,发现同样可以达到目的,但不推荐此法。

Java代码  
  1. package com.itlong.whatsmars.base.sync;
  2. /**
  3. * Created by shenhongxi on 2016/8/12.
  4. * 子线程与主线程是顺序执行的,各子线程之间还是异步的
  5. */
  6. public class JoinTest {
  7. public static void main(String[] args) throws Exception {
  8. Thread t1 = new Thread(new SubRunnable(0));
  9. Thread t2 = new Thread(new SubRunnable(1));
  10. Thread t3 = new Thread(new SubRunnable(2));
  11. long start = System.currentTimeMillis();
  12. t1.start();
  13. t2.start();
  14. t3.start();
  15. t1.join();
  16. t2.join();
  17. t3.join();
  18. System.out.println(System.currentTimeMillis() - start);
  19. System.out.println("Main finished");
  20. }
  21. static class SubRunnable implements Runnable {
  22. private int id = -1;
  23. SubRunnable(int id) {
  24. this.id = id;
  25. }
  26. @Override
  27. public void run() {
  28. try {
  29. System.out.println("hi, I'm id-" + id);
  30. Thread.sleep(9000);
  31. System.out.println(String
  32. .format("Sub Thread %d finished", id));
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }
  38. }

最后,我们顺便提下org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor

Java代码  
  1. public class ThreadPoolTaskExecutor extends ExecutorConfigurationSupport implements SchedulingTaskExecutor {
  2. private final Object poolSizeMonitor = new Object();
  3. private int corePoolSize = 1;
  4. private int maxPoolSize = Integer.MAX_VALUE;
  5. private int keepAliveSeconds = 60;
  6. private boolean allowCoreThreadTimeOut = false;
  7. private int queueCapacity = Integer.MAX_VALUE;
  8. private ThreadPoolExecutor threadPoolExecutor;
  9. /**
  10. * Set the ThreadPoolExecutor's core pool size.
  11. * Default is 1.
  12. * <p><b>This setting can be modified at runtime, for example through JMX.</b>
  13. */
  14. public void setCorePoolSize(int corePoolSize) {
  15. synchronized (this.poolSizeMonitor) {
  16. this.corePoolSize = corePoolSize;
  17. if (this.threadPoolExecutor != null) {
  18. this.threadPoolExecutor.setCorePoolSize(corePoolSize);
  19. }
  20. }
  21. }
  22. /**
  23. * Return the ThreadPoolExecutor's core pool size.
  24. */
  25. public int getCorePoolSize() {
  26. synchronized (this.poolSizeMonitor) {
  27. return this.corePoolSize;
  28. }
  29. }

看到我们熟悉的ThreadPoolExecutor之后,我们瞬间明白了一切。

另外我们脑补下几个接口/类的关系

Java代码  
  1. public interface ExecutorService extends Executor {
  2. <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
  3. throws InterruptedException;
  4. }
  5. public interface Executor {
  6. void execute(Runnable command);
  7. }
  8. public abstract class AbstractExecutorService implements ExecutorService{
  9. public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
  10. // ...
  11. }
  12. }
  13. public class ThreadPoolExecutor extends AbstractExecutorService {
  14. public ThreadPoolExecutor(int corePoolSize,
  15. int maximumPoolSize,
  16. long keepAliveTime,
  17. TimeUnit unit,
  18. BlockingQueue<Runnable> workQueue) {
  19. this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
  20. Executors.defaultThreadFactory(), defaultHandler);
  21. }
  22. }

原文链接:[http://wely.iteye.com/blog/2317944]

主线程等待几个子线程执行完成方案相关推荐

  1. Java多线程、主线程等待所有子线程执行完毕、共享资源

    1.Java创建与启动线程 Java提供两种方式创建和启动线程:1.直接Thread类,2.实现Runable接口. 1.1  继承Thread类 public class myThread exte ...

  2. java主线程等待所有子线程执行完毕再执行

    java主线程等待所有子线程执行完毕在执行,这个需求其实我们在工作中经常会用到,比如用户下单一个产品,后台会做一系列的处理,为了提高效率,每个处理都可以用一个线程来执行,所有处理完成了之后才会返回给用 ...

  3. Java主线程等待所有子线程执行完毕再执行解决办法(转)

    方法一: Thread.join()方法,亲测可行,thread.join()方法 [java] view plain copy Vector<Thread> ts = new Vecto ...

  4. 主线程等待所有子线程结束的4种方法

    目录 主线程不等待子线程全部结束 1.使用CountDownLatch 2.同步屏障CyclicBarrier 2.1.CyclicBarrier使用 2.2.CyclicBarrier复用 2.3. ...

  5. java 父线程_Java父线程(或是主线程)等待所有子线程退出的实例

    导读热词 实例如下: static void testLock1(){ final AtomicInteger waitCount = new AtomicInteger(30000); final ...

  6. python 主程序等待 子线程_Python多线程中主线程等待所有子线程结束的方法

    Python多线程中主线程等待所有子线程结束的方法 发布时间:2020-07-30 14:39:04 来源:亿速云 阅读:77 作者:小猪 这篇文章主要讲解了Python多线程中主线程等待所有子线程结 ...

  7. [Java][Android] 多线程同步-主线程等待全部子线程完毕案例

    有时候我们会遇到这种问题:做一个大的事情能够被分解为做一系列相似的小的事情,而小的事情无非就是參数上有可能不同样而已! 此时,假设不使用线程,我们势必会浪费许多的时间来完毕整个大的事情.而使用线程的话 ...

  8. python主线程有两个子线程、创建两个主函数_Python多任务之线程

    1.1. 线程 threading.Thread(target = 函数名) 线程的运行是没有先后顺序的 主线程死了,子线程必死.子线程结束后,子线程会给子线程收尸. 当调用Thread的时候,不会创 ...

  9. 面试官:如何让主线程等待所有的子线程执行结束之后再执行

    java 主线程等待所有子线程执行完毕在执行,在工作总往往会遇到异步去执行某段逻辑, 然后先处理其他事情, 处理完后再把那段逻辑的处理结果进行汇总(比如用户下单一个产品,后台会做一系列的处理,为了提高 ...

最新文章

  1. 网络资源(9) - TDD视频
  2. 使用@functools.wraps的理由
  3. 服务间调用要通过网关吗_Asp.Net Boilerplate微服务实战(二)架构解析
  4. php网站点击按钮更新程序,php页面 点击按钮执行更新操作
  5. 1405 树的距离之和
  6. PERC5/6 RAID配置中文手册
  7. 变量不在选择列表中_Python3中的表达式运算符
  8. 我用 Python 集齐了支付宝五福!
  9. 电荷为什么不随运动而变化
  10. 【校招VIP】产品行测之逻辑推理
  11. matplotlib常用图形
  12. react兼容safari9_react项目兼容ie浏览器配置
  13. 团队管理,领导的“无为”就是最大“有为”
  14. 算法题_寻找最大连通区域
  15. Pubwin服务端重装(安装)教程
  16. 轻松学编曲,论FL钢琴卷帘
  17. EXCEL 删除表格内的空格和空白字符
  18. 【Zookeeper】ZK 是干什么的?
  19. native2ascii的使用技巧
  20. Google Map API 使用总结

热门文章

  1. HP OSPF 实验(多区域)
  2. python基础知识5——赋值与深浅拷贝——整数和字符串,列表元组字典
  3. 迁移到云端之前需要考虑哪些问题?
  4. mac terminal ssh client shuttle 免输密码
  5. 监控IIS的运行状态
  6. easy-excel导入导出excel(待完善)
  7. Sharepoint学习笔记---Debug--使用ULS Log跟踪Solution错误信息
  8. 统计局:去年12月天然气、电力生产增长较快
  9. Python高级知识点学习(一)
  10. 003——数组(三)count()reset()end()prev()next()current()