多线程执行时,若是一个逻辑须要等若干个线程执行完成后再执行,怎么实现?

实际开发过程当中,尤为是大型的业务系统中或批量处理系统中,咱们一般会用到多线程来进行任务拆分,来提升系统的处理能力。当对业务不断拆分时,多线程各自任务之间也造成了错综复杂的关系。多线程

咱们经常遇到这样的状况,业务模块A 拆分红了 A1 、A2.....An个多线程,来提升处理速度,但是 Ak(1<k<n)这个线程执行时,它有依赖关系,它必须等 Ak-1 和Ak-2这两个进程执行完,才能执行,以避免形成业务混乱,那怎么实现?ide

咱们先定义两个实现多线程任务:函数

任务1:this

public class WorkA1 extends Thread {
   @Override
   public void run() {
      System.out.println("WorkA1 开始执行");
      try {
         Thread.sleep(2000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println("WorkA1 结束执行");
   }
}

任务2:spa

public class WorkA2 extends Thread {
   @Override
   public void run() {
      System.out.println("WorkA2 开始执行");
      try {
         Thread.sleep(1800);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
      System.out.println("WorkA2 结束执行");
   }
}

主线程开始实现是这样的:线程

public class ThreedClient {
   public static void main(String[] args) {
      System.out.println("准备开始执行任务");
      WorkA1 workA1 = new WorkA1();
      WorkA2 workA2 = new WorkA2();
      workA1.start();
      workA2.start();
      System.out.println("执行完成了。");
   }
}

执行结果是:进程

准备开始执行任务
执行完成了。
WorkA1 开始执行
WorkA2 开始执行
WorkA2 结束执行
WorkA1 结束执行

若是咱们想最后打印 “执行完成了”在全部子线程完成后,怎么办呢?开发

咱们对主线程进行改造:it

改造方法1:io

public class ThreedClient {
   public static void main(String[] args) {
      System.out.println("准备开始执行任务");
      WorkA1 workA1 = new WorkA1();
      WorkA2 workA2 = new WorkA2();
      workA1.start();
      workA2.start();
      try {
         workA1.join();
         workA2.join();
      }catch (InterruptedException e){
         e.printStackTrace();
      }
      System.out.println("执行完成了。");
   }
}

改造完成后,在看执行结果:

准备开始执行任务
      WorkA2 开始执行
      WorkA1 开始执行
      WorkA2 结束执行
      WorkA1 结束执行
      执行完成了。

OK,达到咱们的预期了。

改造方法2:

CountDownLatch容许一个或多个线程等待其余线程完成操做。CountDownLatch的构造函数接收一个int类型的参数做为计数器,若是你想等待N个点完成,这里就传入N。当咱们调用countDown方法时,N就会减1,await方法会阻塞当前线程,直到N变成0。
它的原理很简单,就是你须要等待几个任务时,就先定义好,而后任务执行完成一个,计数器减1。看看具体实现:
public class WorkA1 extends Thread {
   private CountDownLatch countDownLatch;
   public WorkA1(CountDownLatch countDownLatch) {
      this.countDownLatch = countDownLatch;
   }
   @Override
   public void run() {
      System.out.println("WorkA1 开始执行");
      try {
         Thread.sleep(2000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }finally {
         countDownLatch.countDown();
      }
      System.out.println("WorkA1 结束执行");
   }
}

Work2的改造跟Work1彻底同样,就再也不单独贴代码了。

看下主线程中的改造:

public class ThreedClient {
   public static void main(String[] args) {
      System.out.println("准备开始执行任务");
      CountDownLatch countDownLatch = new CountDownLatch(2);
      WorkA1 workA1 = new WorkA1(countDownLatch);
      WorkA2 workA2 = new WorkA2(countDownLatch);
      workA1.start();
      workA2.start();
      try {
         countDownLatch.await();
      }catch (InterruptedException e){
         e.printStackTrace();
      }
      System.out.println("执行完成了。");
   }
}

 咱们看下改造后的执行结果:

准备开始执行任务
WorkA1 开始执行
WorkA2 开始执行
WorkA2 结束执行
WorkA1 结束执行
执行完成了。

跟改造1中的效果如出一辙。

相关文章
相关标签/搜索