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

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

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

package concurrency;

public class JoinTest {
public static void main(String[] args) throws InterruptedException{
Thread threadA = new Thread(new JoinJob(),"thread-A");
Thread threadB = new Thread(new JoinJob(),"thread-B");
threadB.start();
threadA.start();
threadA.join();
threadB.join(); System.out.println("main ending...");
}
} class JoinJob implements Runnable{ @Override
public void run() {
System.err.println(Thread.currentThread().getName() + " starting...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " ending..."); } }

运行结果

2.CountDownLatch

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

 package concurrency;

 import java.util.concurrent.CountDownLatch;

 public class CountDownLatchTest {
static CountDownLatch c = new CountDownLatch(6);//如果count大于实际线程数,c.await()会一直等待 public static void main(String[] args) throws InterruptedException{
for (int i = 0; i < c.getCount()/2; i++) {
new Thread(new CountDownJob(c)).start();
new Thread(new CountDownLatchJob2(c)).start(); } System.out.println("waiting " + c.getCount() + " subthread doing");
c.await();//await()会等待c的count值为0,才继续往下执行
System.out.println("all subthread done!");
System.out.println(Thread.currentThread().getName() + " done!");
}
} class CountDownJob implements Runnable{
CountDownLatch cDownLatch; public CountDownJob(CountDownLatch cDownLatch) {
super();
this.cDownLatch = cDownLatch;
} @Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " is doing something...");
Thread.sleep(3000);
cDownLatch.countDown();//线程结束时cDownLatch-1
} catch (InterruptedException e) {
e.printStackTrace();
} } }
class CountDownLatchJob2 implements Runnable{
CountDownLatch cDownLatch; public CountDownLatchJob2(CountDownLatch cDownLatch) {
super();
this.cDownLatch = cDownLatch;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.err.println("thread sleep exception");
}
System.out.println(Thread.currentThread().getName() + " is doing something");
cDownLatch.countDown();//线程结束时cDownLatch-1
} }

运行结果:

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

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

 package concurrency;

 import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier; public class CyclicBarrierTest {
public static void main(String[] args) throws InterruptedException, BrokenBarrierException{
CyclicBarrier cBarrier = new CyclicBarrier(6);
//CyclicBarrier 提供另一个构造函数传入所有线程执行完后需要执行的runnable
// CyclicBarrier cBarrier = new CyclicBarrier(6, new Runnable() {
//
// @Override
// public void run() {
// System.out.println("doing something after all threads done.");
// }
// });
for (int i = 0; i < cBarrier.getParties()/2; i++) {
new Thread(new CyclicBarrierJob1(cBarrier)).start();
new Thread(new CyclicBarrierJob2(cBarrier)).start();
}
//CyclicBarrier 可以重置再次使用,如计算发生错误时可以重置计数器,并让线程重新执行一次。
//而CountDownLatch只可以使用一次
//cBarrier.reset();
}
} class CyclicBarrierJob1 implements Runnable {
CyclicBarrier cBarrier; public CyclicBarrierJob1(CyclicBarrier cBarrier) {
super();
this.cBarrier = cBarrier;
} public void run() {
System.out.println(Thread.currentThread().getName() + " finished phase1");
try {
cBarrier.await();//执行完阶段1的工作之后,等待其他线程全部执行完阶段1,才会继续执行阶段二
} catch (InterruptedException e) {
System.err.println("interrupted!");
} catch (BrokenBarrierException e) {
System.err.println("broken barrier!");
} System.out.println(Thread.currentThread().getName() + " start phase2");
}
}
class CyclicBarrierJob2 implements Runnable {
CyclicBarrier cBarrier; public CyclicBarrierJob2(CyclicBarrier cBarrier) {
super();
this.cBarrier = cBarrier;
} public void run() {
System.out.println(Thread.currentThread().getName() + " finished phase1");
try {
cBarrier.await();//执行完阶段1的工作之后,等待其他线程全部执行完阶段1,才会继续执行阶段二
} catch (InterruptedException e) {
System.err.println("interrupted!");
} catch (BrokenBarrierException e) {
System.err.println("broken barrier!");
}
System.out.println(Thread.currentThread().getName() + " start phase2"); }
}

执行结果:

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

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

 package concurrency;

 import java.util.concurrent.Semaphore;

 public class SemaphoreTest {
public static void main(String[] args) {
final Semaphore semaphore = new Semaphore(3);//限制可以同时访问资源的线程数是10个 for (int i = 0; i < 12; i++) {//新建30个线程
new Thread(new Runnable() { @Override
public void run() {
try {
semaphore.acquire();//获取到许可证才可以访问资源
System.out.println("accessing the database ..");
Thread.sleep(3000);
semaphore.release();//资源访问结束之后释放许可证
} catch (InterruptedException e) {
System.out.println("interrupted!");
} }
}).start();
} }
}

												

等待某(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. 给Ambari集群里安装基于Hive的大数据实时分析查询引擎工具Impala步骤(图文详解)

    不多说,直接上干货! Impala和Hive的关系(详解) 扩展博客 给Clouderamanager集群里安装基于Hive的大数据实时分析查询引擎工具Impala步骤(图文详解) 参考 horton ...

  2. SpringMVC Model,ModelMap ModelAndView

    SpringMVC 调用方法之前会创一个隐含的模型对象(即Model,ModelMap ModelAndView) //@ModelAttribute 先于login方法执行 @ModelAttrib ...

  3. 【杂谈】RN的一点回顾与未来的展望

    从开始到现在,笔者接触RN已经接近半年,适逢各种变化的发生,于是,简单的遐想了一下RN的未来. Airbnb在今年早些时候,宣布了放弃继续使用RN,并且发布了一篇“React Native at Ai ...

  4. 人工智能-深度学习(3)TensorFlow 实战一:手写图片识别

    http://gitbook.cn/gitchat/column/59f7e38160c9361563ebea95/topic/59f7e86d60c9361563ebeee5 wiki.jikexu ...

  5. String Mark Codeforces - 895D

    一看好像会做的样子,就去做了一下,结果 猝不及防地T掉了 赶紧查了一下,没有死循环,复杂度也是对的,无果,于是翻了题解 题解没看懂,但是找到了标程,然后发现我被卡常了... 而且好像当时还过了前10个 ...

  6. magento getMessage 不显示或者显示html标签解决方案

    在模板页面不显示getMessage的解决方案是,在对应的控制器里加上如下代码: $this->_initLayoutMessages('customer/session'); 如果加入后出现如 ...

  7. 转-UIButton定义和设置圆角

    //login button // .h 中定义 UIButton *_loginBtn; @property (strong,nonatomic)UIButton *loginBtn; // .m ...

  8. 211 Add and Search Word - Data structure design 添加与搜索单词 - 数据结构设计

    设计一个支持以下两个操作的数据结构:void addWord(word)bool search(word)search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 . 或 a-z . ...

  9. poj1781In Danger(约瑟夫) 问题

    链接 之前队内赛中的一道题目 当时怎么想也没想到,就一直放到了今天,刚才看另一题的讲解突然看到时拿这个题作为引子来讲的,就仔细看了下. 参考<<具体数学>> p7. Josep ...

  10. [BZOJ1004][HNOI2008]Cards 群论+置换群+DP

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1004 首先贴几个群论相关定义和引理. 群:G是一个集合,*是定义在这个集合上的一个运算. ...