方案(一)CountDownLatch:

使用CountDownLatch+Semaphore方式实现:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore; public class TestABC {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch=new CountDownLatch(2);
Semaphore semaphoreC = new Semaphore(1); Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(newjava.util.Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
countDownLatch.countDown();
}
}, "Thread-A"); Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(newjava.util.Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
countDownLatch.countDown();
}
}, "Thread-B"); Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
try {
semaphoreC.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
semaphoreC.release();
}
}, "Thread-C"); // 占用C锁,直到A/B线程完成后,才释放C锁。
semaphoreC.acquire(); threadA.start();
threadB.start();
threadC.start(); countDownLatch.await();
// 释放C锁,让C线程有获取锁的可能
semaphoreC.release(); }
}

上边使用CountDownLatch+Semaphore方式实现,但是缺点:上边这种方式会导致线程阻塞情况。下边这种方案是可以实现不阻塞线程的用法:

import java.util.concurrent.CountDownLatch;

public class TestABC {
public static void main(String[] args) throws InterruptedException {
CountDownLatch countDownLatch=new CountDownLatch(2); Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(new java.util.Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
countDownLatch.countDown();
}
}, "Thread-A"); Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(new java.util.Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
countDownLatch.countDown();
}
}, "Thread-B"); Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
// 在C中等待A/B運算結束
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
throw new RuntimeException("CountDownLatch等待失败。。。",e);
} System.out.println(Thread.currentThread().getName());
}
}, "Thread-C"); threadA.start();
threadB.start();
threadC.start();
}
}

方案(二):CyclicBarrier

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier; public class TestABC {
public static void main(String[] args) throws InterruptedException {
CyclicBarrier cyclicBarrier=new CyclicBarrier(3); Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(new java.util.Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()); // 冲破栅栏代表A线程结束
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
throw new RuntimeException("cylicBarrier.await()拋出異常:",e);
}
}
}, "Thread-A"); Thread threadB = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(new java.util.Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()); // 冲破栅栏代表B线程结束
try {
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
throw new RuntimeException("cylicBarrier.await()拋出異常:",e);
}
}
}, "Thread-B"); Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
// 等待前两个(A/B)线程结束,只有前两个(A/B)线程结束了才能满足3个线程都冲破栅栏,
try {
// 等待栅栏被冲破,冲破栅栏的条件是:A/B/C三个线程都到达await()。
// 只有栅栏冲破,才能向下执行,否则先到达的线程等待。
cyclicBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
throw new RuntimeException("cylicBarrier.await()拋出異常:",e);
}
// 满足了三个线程都冲破栅栏才向下执行
System.out.println(Thread.currentThread().getName());
}
}, "Thread-C"); threadA.start();
threadB.start();
threadC.start();
}
}

Java-JUC(十二):有3个线程。线程A和线程B并行执行,线程C需要A和B执行完成后才能执行。可以怎么实现?的更多相关文章

  1. Java基础十二--多态是成员的特点

    Java基础十二--多态是成员的特点 一.特点 1,成员变量. 编译和运行都参考等号的左边. 覆盖只发生在函数上,和变量没关系. Fu f = new Zi();System.out.println( ...

  2. “全栈2019”Java第九十二章:外部类与内部类成员覆盖详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  3. “全栈2019”Java第十二章:变量

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  4. “全栈2019”Java第二十二章:控制流程语句中的决策语句if-else

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. JAVA提高十二:HashMap深入分析

    首先想说的是关于HashMap源码的分析园子里面应该有很多,并且都是分析得很不错的文章,但是我还是想写出自己的学习总结,以便加深自己的理解,因此就有了此文,另外因为小孩过来了,因此更新速度可能放缓了, ...

  6. Java主线程在子线程执行完毕后再执行

    一.join() Thread中的join()方法就是同步,它使得线程之间由并行执行变为串行执行. public class MyJoinTest { public static void main( ...

  7. C# 本进程执行完毕后再执行下一线程

    最近做了一套MES集成系统,由上料到成品使自动化运行,其中生产过程是逐步的,但是每一个动作都需要独立的线程进行数据监听,那么就需要实现线程等待. 代码: using System; using Sys ...

  8. java——第十二章 异常处理和文本I/O

    1.异常处理: 使用try_throw_catch块模块 优点:将检测错误(由被调用的方法完成)从处理错误(由调用方法完成)中分离出来. 例子: package test; import java.u ...

  9. Java系列学习(十二)-开始Eclipse

    1.用Eclipse来写一个HelloWorld (1)选择工作空间 工作空间其实就是我们写的源代码所在的目录 (2)创建一个Java项目 [File-New-Java Project] (3)创建包 ...

随机推荐

  1. python多任务的实现:线程,进程,协程

    什么叫“多任务”呢?简单地说,就是操作系统可以同时运行多个任务.打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行.还有很多任务悄悄地在后 ...

  2. 使用PATH变量进行Linux权限升级技巧

    0x00 前言 在解决了几个OSCP挑战之后,我们决定写一篇关于用于Linux权限升级的各种方法的文章,这对我们的读者在其渗透测试项目中有所帮助.在本文中,我们将学习“使用$path变量的各种方法”以 ...

  3. js 高阶函数之柯里化

    博客地址:https://ainyi.com/74 定义 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且 ...

  4. ovirt平台新建kvm操作

    登录后点击管理门户,随后计算-->虚拟机--> 新建 一般情况下需要操作的选项如下: 普通: 操作系统:linux 优化目标:服务器 描述:自定义 nic1:选择默认的网络 系统: 内存, ...

  5. 从零搭建consul

    从零搭建consul 原文链接:https://blog.csdn.net/weixin_42107541/article/details/87640807#2linux_25 从零搭建consul1 ...

  6. 使用ZeroClipboard 复制指定内容到剪切板

    有些时候,我们希望让用户在网页上完成某个操作就能自动将指定的内容复制到用户计算机的剪贴板中.但是出于安全原因,大多数现代浏览器都未提供通用的剪贴板复制接口(或即便有,也默认被禁用).只有IE浏览器可以 ...

  7. MySQL创建用户和加限权

    目录 1.权限管理 1.1对新用户增删改 1.2对当前的用户授权管理 1.权限管理 ​ 我们知道我们的最高权限管理者是root用户,它拥有着最高的权限操作.包括select.update.delete ...

  8. Linux文件系统及管理

    Linux文件系统及管理 一.Linux系统的文件系统与目录结构   Linux系统的文件目录结构为一个单根倒置的树结构,具体表现如下图: 从CentOS7开始,以下目录与之前的版本发生变化 ◆/bi ...

  9. 从url中下载资源(目前测试只有照片,文件类的没有进行测试)

    首先:是工具类: public class DownLoadUtils { /** * 从网络Url中下载文件 * * @param urlStr url路径 * @param fileName 文件 ...

  10. SpringCloud过滤filter

    目录 配置文件 application.yml eureka: client: service-url: defaultZone: http://localhost:8001/eureka serve ...