Java-JUC(十二):有3个线程。线程A和线程B并行执行,线程C需要A和B执行完成后才能执行。可以怎么实现?
方案(一)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执行完成后才能执行。可以怎么实现?的更多相关文章
- Java基础十二--多态是成员的特点
Java基础十二--多态是成员的特点 一.特点 1,成员变量. 编译和运行都参考等号的左边. 覆盖只发生在函数上,和变量没关系. Fu f = new Zi();System.out.println( ...
- “全栈2019”Java第九十二章:外部类与内部类成员覆盖详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第十二章:变量
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十二章:控制流程语句中的决策语句if-else
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- JAVA提高十二:HashMap深入分析
首先想说的是关于HashMap源码的分析园子里面应该有很多,并且都是分析得很不错的文章,但是我还是想写出自己的学习总结,以便加深自己的理解,因此就有了此文,另外因为小孩过来了,因此更新速度可能放缓了, ...
- Java主线程在子线程执行完毕后再执行
一.join() Thread中的join()方法就是同步,它使得线程之间由并行执行变为串行执行. public class MyJoinTest { public static void main( ...
- C# 本进程执行完毕后再执行下一线程
最近做了一套MES集成系统,由上料到成品使自动化运行,其中生产过程是逐步的,但是每一个动作都需要独立的线程进行数据监听,那么就需要实现线程等待. 代码: using System; using Sys ...
- java——第十二章 异常处理和文本I/O
1.异常处理: 使用try_throw_catch块模块 优点:将检测错误(由被调用的方法完成)从处理错误(由调用方法完成)中分离出来. 例子: package test; import java.u ...
- Java系列学习(十二)-开始Eclipse
1.用Eclipse来写一个HelloWorld (1)选择工作空间 工作空间其实就是我们写的源代码所在的目录 (2)创建一个Java项目 [File-New-Java Project] (3)创建包 ...
随机推荐
- 英语affrike非洲
中文名称:阿非利加洲(全称) 外文名称:Africa 别 名:Affrike 行政区类别洲 下辖地区北非.东非.西非.中非.南非 地理位置:东濒印度洋,西临大西洋,北至地中海,南至好望角 面 积:30 ...
- Spring IOC 总结
IOC 简介 IOC是(Inversion of Control,控制反转)的简写.Spring提供IOC容器,将对象间的依赖关系交由Spring进行控制,避免硬编码所造成的的过度程序耦合.它由DI( ...
- Windows系统Apache下载和安装
一.Apache的下载 1.访问Apache官网:https://httpd.apache.org 2.选择Windows版本下载 3.下载完成后解压缩,把文件放到自己想放的盘 二.Apache的安装 ...
- 为安卓项目添加FileProvider
简单记录 android7.0开始出现FileProvider.从一个小白角度看需要注意这几点: Manifest.xml中添加provider节点 添加xml文件 模块的build.gradle中添 ...
- python基础---python基础语法
1.常用符号 逗号,枚举:一个函数有多个参数sum(1,2) 等于,赋值:把一个值,给一个变量,a=1 括号,函数的参数部分sum(x,y) 冒号,一个子过程的开始 双引号/单引号:表示字符串 运算符 ...
- Electrification Plan 最小生成树(prim+krusl+堆优化prim)
题目 题意: 无向图,给n个城市,n*n条边,每条边都有一个权值 代表修路的代价,其中有k个点有发电站,给出这k个点的编号,要每一个城市都连到发电站,问最小的修路代价. 思路: prim:把发电站之间 ...
- Linux TTY介绍
1. TTY介绍 TTY(TeleType)指Linux中的一类终端(Terminal)设备, 是一种字符设备 在Linux中, tty可分为如下几类- 串行端口终端(serial port term ...
- danci3
permit 英 [pə'mɪt] 美 [pɚ'mɪt] vi. 许可:允许 vt. 许可:允许 n. 许可证,执照 encapsulate 英 [ɪn'kæpsjʊleɪt; en-] 美 [ɪn' ...
- 数据分析 - Numpy
简介 Numpy是高性能科学计算和数据分析的基础包.它也是pandas等其他数据分析的工具的基础,基本所有数据分析的包都用过它.NumPy为Python带来了真正的多维数组功能,并且提供了丰富的函数库 ...
- Redis-基础介绍
Redis 基础介绍 一.Redis介绍 二.Redis和Memecache的不同 三.Redis的最佳应用场景: 四.Redis支持的键值类型 五.安装Redis 六.Redis启动方式 七.Red ...