多线程执行时,如果一个逻辑需要等若干个线程执行完成后再执行,怎么实现?
2018-12-14 11:05
10 查看
实际开发过程中,尤其是大型的业务系统中或批量处理系统中,我们通常会用到多线程来进行任务拆分,来提高系统的处理能力。当对业务不断拆分时,多线程各自任务之间也形成了错综复杂的关系。
我们常常遇到这样的情况,业务模块A 拆分成了 A1 、A2.....An个多线程,来提高处理速度,可是 Ak(1<k<n)这个线程执行时,它有依赖关系,它必须等 Ak-1 和Ak-2这两个进程执行完,才能执行,以免造成业务混乱,那怎么实现?
我们先定义两个实现多线程任务:
任务1:
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:
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 结束执行
如果我们想最后打印 “执行完成了”在所有子线程完成后,怎么办呢?
我们对主线程进行改造:
改造方法1:
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中的效果一模一样。
(adsbygoogle = window.adsbygoogle || []).push({});相关文章推荐
- 如果一个类通过继承Thread来实现多线程的话,则不适合多个线程共享资源,而通过实现Runnable就可以做到这一点
- python里怎么实现多个协程一起执行,只要完成一个就返回一个协程
- 【一个批量计算的调度系统的设计与实现】如果需要对成千上万的网络抓包数据文件在规定的时间内进行解析,应该怎么做?
- 编写一个聊天程序:有接收数据部分,和发数据的部分, 这两部分需要同时执行,使用多线程实现,一个控制接收,一个控制发送
- 有a、b、c、d 4个异步请求,如何判断a、b、c、d都完成执行?如果需要a、b、c、d顺序执行,该如何实现?
- 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法
- 多线程之join()方法---(Thread提供的让一个线程等待另一个线程完成的方法)
- 需要实现对一个字符串的处理,首先将该字符串首尾的空格去掉,如果字符串中间还有连续空格的话,仅保留一个空格,即允许字符串中间有多个空格,但连续的空格数不可超过一个
- CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
- 生产者消费者问题 这是一个非常经典的多线程题目,题目大意如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者
- C++实现线程同步的几种方式 线程同步是指同一进程中的多个线程互相协调工作从而达到一致性。之所以需要线程同步,是因为多个线程同时对一个数据对象进行修改操作时,可能会对数据造成破坏,下面是多
- 如果页面需要很长时间才能完成,那么执行前使用
- 用js实现在加载完成一个页面后自动执行一个方法
- Java 多线程实现的三种方法,附两个线程执行不同的输出
- Java 多线程中。两个线程交替执行,一个输出偶数,一个输出奇数
- java多线程-使用ReentrantLock实现线程的顺序执行
- 使用管道流和多线程完成以下任务要求: 一个线程对象t1 会从控制台中不停的读取信息,读到之后把数据交给管道输出流,把数据写到管道里面 ,另一个线程对象t2 不停的使用管道输入流从管道
- 如果某个页面上点击按钮发起了一个http url请求,去执行一个action,但是还没等这个action完成,我就刷新了这个页面,然后又点击了这个按钮,这样之前的那次http url请求还在执行吗?
- 关于java中怎么终止一个线程的执行
- Linux多线程编程的时候怎么查看一个进程中的某个线程是否存活