JUC学习笔记(三)
JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html
JUC学习笔记(二)https://www.cnblogs.com/lm66/p/15118813.html
1、线程间通信
线程间通信的模型有两种:共享内存和消息传递,以下方式都是基本这两种模型来实现的。我们来基本一道面试常见的题目来分析
场景---两个线程,一个线程对当前数值加 1,另一个线程对当前数值减 1,要求用线程间通信
1.1、synchronized 方案
public class ThreadDemo1 {
public static void main(String[] args) {
Share share = new Share();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
share.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "AA").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
share.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "BB").start();
}
}
class Share {
private int num = 0;
public synchronized void increment() throws Exception {
while (num != 0) {
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + "::" + num);
this.notifyAll();
}
public synchronized void decrement() throws Exception {
while (num != 1) {
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName() + "::" + num);
this.notifyAll();
}
}
1.2、Lock方案
public class ThreadDemo2 {
public static void main(String[] args) {
Share2 share = new Share2();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
share.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "AA").start();
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
share.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
}, "BB").start();
}
}
class Share2 {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private int num = 0;
public void increment() throws Exception {
lock.lock();
try {
while (num != 0) {
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName() + "::" + num);
condition.signalAll();
} finally {
lock.unlock();
}
}
public void decrement() throws Exception {
lock.lock();
try {
while (num != 1) {
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName() + "::" + num);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
1.3、线程间定制化通信
1.3.1、案例介绍
问题: A 线程打印 5 次 A,B 线程打印 10 次 B,C 线程打印 15 次 C,按照此顺序循环 10 轮
1.3.2、实现流程
public class ThreadDemo3 {
public static void main(String[] args) {
ShareResource shareResource = new ShareResource();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
shareResource.print5(i);
} catch (Exception e) {
}
}
},"AA").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
shareResource.print10(i);
} catch (Exception e) {
}
}
},"BB").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
shareResource.print15(i);
} catch (Exception e) {
}
}
},"CC").start();
}
}
class ShareResource {
// 定义标志位
private int flag = 1;
// 创建Lock锁
private Lock lock = new ReentrantLock();
private Condition c1 = lock.newCondition();
private Condition c2 = lock.newCondition();
private Condition c3 = lock.newCondition();
public void print5(int loop) throws Exception {
lock.lock();
try {
// 判断。防止虚假唤醒
while (flag != 1) {
// 等待
c1.await();
}
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "::" + loop);
}
// 修改标志位
flag = 2;
// 通知
c2.signal();
} finally {
lock.unlock();
}
}
public void print10(int loop) throws Exception {
lock.lock();
try {
while (flag != 2) {
c2.await();
}
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "::" + loop);
}
flag = 3;
c3.signal();
} finally {
lock.unlock();
}
}
public void print15(int loop) throws Exception {
lock.lock();
try {
while (flag != 3) {
c3.await();
}
for (int i = 0; i < 15; i++) {
System.out.println(Thread.currentThread().getName() + "::" + loop);
}
flag = 1;
c1.signal();
} finally {
lock.unlock();
}
}
}

JUC学习笔记(三)的更多相关文章
- JUC学习笔记(六)
JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html JUC学习笔记(二)https://www.cnblogs.com/lm66/p/1511 ...
- JUC学习笔记(五)
JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html JUC学习笔记(二)https://www.cnblogs.com/lm66/p/1511 ...
- JUC学习笔记(四)
JUC学习笔记(一)https://www.cnblogs.com/lm66/p/15118407.html JUC学习笔记(二)https://www.cnblogs.com/lm66/p/1511 ...
- JUC学习笔记——进程与线程
JUC学习笔记--进程与线程 在本系列内容中我们会对JUC做一个系统的学习,本片将会介绍JUC的进程与线程部分 我们会分为以下几部分进行介绍: 进程与线程 并发与并行 同步与异步 线程详解 进程与线程 ...
- JUC学习笔记——共享模型之管程
JUC学习笔记--共享模型之管程 在本系列内容中我们会对JUC做一个系统的学习,本片将会介绍JUC的管程部分 我们会分为以下几部分进行介绍: 共享问题 共享问题解决方案 线程安全分析 Monitor ...
- JUC学习笔记——共享模型之内存
JUC学习笔记--共享模型之内存 在本系列内容中我们会对JUC做一个系统的学习,本片将会介绍JUC的内存部分 我们会分为以下几部分进行介绍: Java内存模型 可见性 模式之两阶段终止 模式之Balk ...
- Oracle学习笔记三 SQL命令
SQL简介 SQL 支持下列类别的命令: 1.数据定义语言(DDL) 2.数据操纵语言(DML) 3.事务控制语言(TCL) 4.数据控制语言(DCL)
- [Firefly引擎][学习笔记三][已完结]所需模块封装
原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读: 笔记三主要就是各个模块的封装了,这里贴 ...
- JSP学习笔记(三):简单的Tomcat Web服务器
注意:每次对Tomcat配置文件进行修改后,必须重启Tomcat 在E盘的DATA文件夹中创建TomcatDemo文件夹,并将Tomcat安装路径下的webapps/ROOT中的WEB-INF文件夹复 ...
随机推荐
- Python | 更换pip源到国内镜像
pip国内的一些镜像 阿里云 https://mirrors.aliyun.com/pypi/simple/ 中国科技大学 https://pypi.mirrors.ustc.edu.cn/simpl ...
- Redis:Redis的安装
Redis优势 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s . 丰富的数据类型 – Redis支持二进制案例的 Strings, Li ...
- Https:Java代码设置使用证书访问Https
设置证书进行访问或被访问操作 String keyStore = "keyStore的文件路径": String KEY_STORE_PWD = "1234"; ...
- ExtJs4学习(十)Grid单元格换色和行换色的方法
Grid单元格换色 { text:'类别', dataIndex:'type', align:'center', renderer:function(value,metaData){ console. ...
- [心得体会]Spring容器的初始化
1. Spring容器的初始化过程 public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) { ...
- 自己动手模拟spring的IOC
我们这里是模拟spring,主要模拟spring中的IOC功能,所以在此我们一样要在service层中定义dao的实例,当然不用new出来,我们就通过spring的IOC把这里的dao层注入进来.不要 ...
- MVC 与 三层架构
https://www.bilibili.com/video/av29086718/?p=24 MVC: MVC与三层架构进行比较:
- rename 批量修改文件名
1.rename的用法 rename与mv的区别就是mv只能对单个文件重命名,而rename可以批量修改文件名 linux中的rename有两种版本,一种是C语言版的,一种是Perl版的.早期的Lin ...
- ROS2学习之旅(4)——理解ROS2 Graph中的节点
ROS(2)图(ROS(2) graph)是一个同时处理数据的基于ROS2元素的网络,它包含了所有的可执行文件以及它们之间的连接.图中的基本元素包括:节点(nodes).话题(topics).服务(s ...
- WIN10小技巧
WIN10激活: powershell管理员运行slmgr /skms kms.03k.orgslmgr /ato CMD:%TEMP% 全选垃圾,删除 手机投屏到WIN10:win+i---系统-- ...