实际开发过程当中,尤为是大型的业务系统中或批量处理系统中,咱们一般会用到多线程来进行任务拆分,来提升系统的处理能力。当对业务不断拆分时,多线程各自任务之间也造成了错综复杂的关系。多线程
咱们经常遇到这样的状况,业务模块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:
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中的效果如出一辙。