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)创建包 ...
随机推荐
- 基于webpack的前端工程化开发解决方案探索(二):代码分割与图片加载
今天我们继续来进行webpack工程化开发的探索! 首先来验证上一篇文章 基于webpack的前端工程化开发解决方案探索(一):动态生成HTML 中的遗留问题:webpack将如何处理按需加载的 ...
- nginx服务器除了更目录可以访问,其他都出现404
配置如下: listen 80; server_name www.hongtaofei.com; location / { root /home/www/shop/public; index inde ...
- php和mysql交互 面向对象
不返回结果集 <?php //使用对象属性和方法来插入数据 header('Content-type:text/html;carset=utf8'); $con=new mysqli('loca ...
- linux下nm命令的使用
linux下强大的文件分析工具 -- nm 什么是nm nm命令是linux下自带的特定文件分析工具,一般用来检查分析二进制文件.库文件.可执行文件中的符号表,返回二进制文件中各段的信息. 目标文件. ...
- js面向对象--由浅入深
基本概念 ECMA关于对象的定义是:”无序属性的集合,其属性可以包含基本值.对象或者函数.“对象的每个属性或方法都有一个名字,而每个名字都映射到一个值. 类 在现实生活中,相似的对象之间往往都有一些共 ...
- 【转】GnuPG使用介绍
一.什么是 GPG 要了解什么是 GPG,就要先了解 PGP. 1991 年,程序员 Phil Zimmermann 为了避开政府监视,开发了加密软件 PGP.这个软件非常好用,迅速流传开来,成了许多 ...
- JQuery DOM操作(属性操作/样式操作/文档过滤)
jQuery——入门(三)JQuery DOM操作(属性操作/样式操作/文档过滤) 一.DOM属性操作 1.属性 (1).attr() 方法 语法:$(selector).attr(name|prop ...
- Linux CentOS7.x安装docker全过程
1.在安装docker之前,首先使用yum -y remove docker命令移除系统中已有的旧版本的docker yum -y remove docker 这里显示该系统没有安装过docker: ...
- python开发应用之-时间戳
golang 获取时间戳用time.Now().Unix(),格式化时间用t.Format,解析时间用time.Parse package main import ( "fmt" ...
- LeetCode 881. Boats to Save People
原题链接在这里:https://leetcode.com/problems/boats-to-save-people/ 题目: The i-th person has weight people[i] ...