1.main线程中先调用threadA.join() ,再调用threadB.join()实现A->B->main线程的执行顺序

调用threadA.join()时,main线程会挂起,等待threadA执行完毕返回后再执行,到执行threadB.join()时再挂起,待threadB执行完毕返回继续执行main

使用场景:线程B依赖线程A的计算结果的场景

  1. package concurrency;
  2.  
  3. public class JoinTest {
  4. public static void main(String[] args) throws InterruptedException{
  5. Thread threadA = new Thread(new JoinJob(),"thread-A");
  6. Thread threadB = new Thread(new JoinJob(),"thread-B");
  7. threadB.start();
  8. threadA.start();
  9. threadA.join();
  10. threadB.join();
  11.  
  12. System.out.println("main ending...");
  13. }
  14. }
  15.  
  16. class JoinJob implements Runnable{
  17.  
  18. @Override
  19. public void run() {
  20. System.err.println(Thread.currentThread().getName() + " starting...");
  21. try {
  22. Thread.sleep(3000);
  23. } catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. System.out.println(Thread.currentThread().getName() + " ending...");
  27.  
  28. }
  29.  
  30. }

运行结果

2.CountDownLatch

使用场景:多线程数据计算时需要先分几个线程计算第一步骤的数据,再合并一个线程计算第二步

  1. package concurrency;
  2.  
  3. import java.util.concurrent.CountDownLatch;
  4.  
  5. public class CountDownLatchTest {
  6. static CountDownLatch c = new CountDownLatch(6);//如果count大于实际线程数,c.await()会一直等待
  7.  
  8. public static void main(String[] args) throws InterruptedException{
  9. for (int i = 0; i < c.getCount()/2; i++) {
  10. new Thread(new CountDownJob(c)).start();
  11. new Thread(new CountDownLatchJob2(c)).start();
  12.  
  13. }
  14.  
  15. System.out.println("waiting " + c.getCount() + " subthread doing");
  16. c.await();//await()会等待c的count值为0,才继续往下执行
  17. System.out.println("all subthread done!");
  18. System.out.println(Thread.currentThread().getName() + " done!");
  19. }
  20. }
  21.  
  22. class CountDownJob implements Runnable{
  23. CountDownLatch cDownLatch;
  24.  
  25. public CountDownJob(CountDownLatch cDownLatch) {
  26. super();
  27. this.cDownLatch = cDownLatch;
  28. }
  29.  
  30. @Override
  31. public void run() {
  32. try {
  33. System.out.println(Thread.currentThread().getName() + " is doing something...");
  34. Thread.sleep(3000);
  35. cDownLatch.countDown();//线程结束时cDownLatch-1
  36. } catch (InterruptedException e) {
  37. e.printStackTrace();
  38. }
  39.  
  40. }
  41.  
  42. }
  43. class CountDownLatchJob2 implements Runnable{
  44. CountDownLatch cDownLatch;
  45.  
  46. public CountDownLatchJob2(CountDownLatch cDownLatch) {
  47. super();
  48. this.cDownLatch = cDownLatch;
  49. }
  50. @Override
  51. public void run() {
  52. try {
  53. Thread.sleep(1000);
  54. } catch (InterruptedException e) {
  55. System.err.println("thread sleep exception");
  56. }
  57. System.out.println(Thread.currentThread().getName() + " is doing something");
  58. cDownLatch.countDown();//线程结束时cDownLatch-1
  59. }
  60.  
  61. }

运行结果:

3.可循环使用的同步屏障CyclicBarrier

使用场景:多线程计算数据,等待全部线程执行完阶段一的工作之后,再执行后面的阶段工作

  1. package concurrency;
  2.  
  3. import java.util.concurrent.BrokenBarrierException;
  4. import java.util.concurrent.CyclicBarrier;
  5.  
  6. public class CyclicBarrierTest {
  7. public static void main(String[] args) throws InterruptedException, BrokenBarrierException{
  8. CyclicBarrier cBarrier = new CyclicBarrier(6);
  9. //CyclicBarrier 提供另一个构造函数传入所有线程执行完后需要执行的runnable
  10. // CyclicBarrier cBarrier = new CyclicBarrier(6, new Runnable() {
  11. //
  12. // @Override
  13. // public void run() {
  14. // System.out.println("doing something after all threads done.");
  15. // }
  16. // });
  17. for (int i = 0; i < cBarrier.getParties()/2; i++) {
  18. new Thread(new CyclicBarrierJob1(cBarrier)).start();
  19. new Thread(new CyclicBarrierJob2(cBarrier)).start();
  20. }
  21. //CyclicBarrier 可以重置再次使用,如计算发生错误时可以重置计数器,并让线程重新执行一次。
  22. //而CountDownLatch只可以使用一次
  23. //cBarrier.reset();
  24. }
  25. }
  26.  
  27. class CyclicBarrierJob1 implements Runnable {
  28. CyclicBarrier cBarrier;
  29.  
  30. public CyclicBarrierJob1(CyclicBarrier cBarrier) {
  31. super();
  32. this.cBarrier = cBarrier;
  33. }
  34.  
  35. public void run() {
  36. System.out.println(Thread.currentThread().getName() + " finished phase1");
  37. try {
  38. cBarrier.await();//执行完阶段1的工作之后,等待其他线程全部执行完阶段1,才会继续执行阶段二
  39. } catch (InterruptedException e) {
  40. System.err.println("interrupted!");
  41. } catch (BrokenBarrierException e) {
  42. System.err.println("broken barrier!");
  43. }
  44.  
  45. System.out.println(Thread.currentThread().getName() + " start phase2");
  46. }
  47. }
  48. class CyclicBarrierJob2 implements Runnable {
  49. CyclicBarrier cBarrier;
  50.  
  51. public CyclicBarrierJob2(CyclicBarrier cBarrier) {
  52. super();
  53. this.cBarrier = cBarrier;
  54. }
  55.  
  56. public void run() {
  57. System.out.println(Thread.currentThread().getName() + " finished phase1");
  58. try {
  59. cBarrier.await();//执行完阶段1的工作之后,等待其他线程全部执行完阶段1,才会继续执行阶段二
  60. } catch (InterruptedException e) {
  61. System.err.println("interrupted!");
  62. } catch (BrokenBarrierException e) {
  63. System.err.println("broken barrier!");
  64. }
  65. System.out.println(Thread.currentThread().getName() + " start phase2");
  66.  
  67. }
  68. }

执行结果:

4.可控制并发线程数的信号量Semaphore

使用场景:控制同时访问特定资源的线程数量

  1. package concurrency;
  2.  
  3. import java.util.concurrent.Semaphore;
  4.  
  5. public class SemaphoreTest {
  6. public static void main(String[] args) {
  7. final Semaphore semaphore = new Semaphore(3);//限制可以同时访问资源的线程数是10个
  8.  
  9. for (int i = 0; i < 12; i++) {//新建30个线程
  10. new Thread(new Runnable() {
  11.  
  12. @Override
  13. public void run() {
  14. try {
  15. semaphore.acquire();//获取到许可证才可以访问资源
  16. System.out.println("accessing the database ..");
  17. Thread.sleep(3000);
  18. semaphore.release();//资源访问结束之后释放许可证
  19. } catch (InterruptedException e) {
  20. System.out.println("interrupted!");
  21. }
  22.  
  23. }
  24. }).start();
  25. }
  26.  
  27. }
  28. }

  1.  

等待某(N)个线程执行完再执行某个线程的几种方法(Thread.join(),CountDownLatch,CyclicBarrier,Semaphore)的更多相关文章

  1. C# 多线程join的用法,等待多个子线程结束后再执行主线程

    等待多个子线程结束后再执行主线程 class MultiThread{ #region join test public void MultiThreadTest() { Thread[] ths = ...

  2. ExtJS 等待两个/多个store加载完再执行操作的方法

    ExtJS是一种主要用于创建前端用户界面,是一个基本与后台技术无关的前端ajax框架. Extjs加载Store是异步加载的,这有很多好处.但是当我们要在两个或多个不同的store加载完再执行一些操作 ...

  3. CountDownLatch用法---等待多个线程执行完才执行

    CountDownLatch用法---等待多个线程执行完才执行 CountDownLatch用法---等待多个线程执行完才执行 CountDownLatch用法---等待多个线程执行完才执行 Coun ...

  4. jquery each循环遍历完再执行的方法 因为each是异步的 所以要加计数器.

    query each循环遍历完再执行的方法因为each是异步的 所以要加计数器.var eachcount=0;$(“.emptytip”).each(function(){ eachcount++c ...

  5. jquery each循环遍历完再执行的方法

    jquery each循环遍历完再执行的方法 因为each是异步的 所以要加计数器. var eachcount=0; <pre> $(".emptytip").eac ...

  6. flock防止crontab脚本周期内未执行完重复执行(转)

    如果某脚本要运行30分钟,可以在Crontab里把脚本间隔设为至少一小时来避免冲突.而比较糟的情况是可能该脚本在执行周期内没有完成,接着第二个脚本又开始运行了.如何确保只有一个脚本实例运行呢?一个好用 ...

  7. javascript 中的location.href 并不是立即执行的,是在所在function 执行完之后执行的。

    javascript 中的location.href 并不是立即执行的,是在所在function 执行完之后执行的. 1 function getUrl(tp) { if (tp == 'd') { ...

  8. 页面自动执行(加载)js的几种方法

    https://www.cnblogs.com/2huos/p/js-autorun.html 一.JS方法1.最简单的调用方式,直接写到html的body标签里面: <html> < ...

  9. 从数据表中随机抽取n条数据有哪几种方法(join实现可以先查数据然后再拼接)

    从数据表中随机抽取n条数据有哪几种方法(join实现可以先查数据然后再拼接) 一.总结 一句话总结:最好的是这个:"SELECT * FROM table WHERE id >= (( ...

随机推荐

  1. Ruby 数式匹配器

    str = "x^2 + 12317         +X^2 -       Length" str = "      x    ^  2  + y           ...

  2. python 面向对象二 类和实例

    一.类和实例 面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法, ...

  3. bzoj 1497 [NOI2006]最大获利【最大权闭合子图+最小割】

    不要被5s时限和50000点数吓倒!大胆网络流!我一个5w级别的dinic只跑了1s+! 看起来没有最大权闭合子图的特征--限制,实际上还是有的. 我们需要把中转站看成负权点,把p看成点权,把客户看成 ...

  4. win7/8系统中php5.3和5.4、5.5不能加载php_curl.dll解决办法

    win7/8系统中php5.3和5.4.5.5不能加载php_curl.dll解决办法   作者:用户 来源:互联网 时间:2016-06-23 18:54:33 php变量注释系统模块 摘要: 本文 ...

  5. 贪心+模拟 ZOJ 3829 Known Notation

    题目传送门 /* 题意:一串字符串,问要最少操作数使得成为合法的后缀表达式 贪心+模拟:数字个数 >= *个数+1 所以若数字少了先补上在前面,然后把不合法的*和最后的数字交换,记录次数 岛娘的 ...

  6. 专 linux命令之set x详解

    set -x与set +x指令   用于脚本调试.set是把它下面的命令打印到屏幕 set -x 是开启 set +x是关闭 set -o是查看 (xtrace),set去追中一段代码的显示情况. 执 ...

  7. [转]linux之date命令MYSQL用户管理

    转自:http://www.cnblogs.com/hencehong/archive/2013/03/19/mysql_user.html 一.        用户登录 格式: mysql -h主机 ...

  8. Windows 7操作系统下PHP 7的安装与配置(图文详解)

    前提博客 Windows 7操作系统下Apache的安装与配置(图文详解) 从官网下载           PHP的官网 http://www.php.net/         特意,新建这么一个目录 ...

  9. 使用ImageMagick处理图片后导致图片变大的问题

    最新在使用ImageMagick处理图片时,发现有时经过处理的图片变大的问题. 例如原图为27K,经处理后的图片会变为77K. 先看测试代码: // imgtest.cpp : 定义控制台应用程序的入 ...

  10. AJPFX关于this用法和注意事项

    this:代表对象.就是所在函数所属对象的引用.哪个对象调用了this所在的函数,this就代表哪个对象,就是哪个对象的引用.开发时在定义功能时,如果该功能内部使用到了调用该功能的对象,这时就用thi ...