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如何设计面向对象的类(上)
Python是一门高级语言,支持面向对象设计,如何设计一个符合Python风格的面向对象的类,是一个比较复杂的问题,本文提供一个参考,表达一种思路,探究一层原理. 目标 期望实现的类具有以下基本行为: ...
- SystemVerilog 中的相等运算符:== or === ?
1. 四值逻辑的逻辑运算 在对比SystemVerilog中的相等运算符之前,先来看一下三种最基本的逻辑运算符,下文中以·表示与运算,以+表示或运算,以'表示非运算.我们都知道在逻辑代数中,只有0和1 ...
- Spring学习日记02_IOC_属性注入_其他类型属性
ICO操作Bean管理(xml注入其它类型属性) 字面量 null值 <property name="address"> <null></null&g ...
- 让你发布的nuget包支持源代码调试
前情概要 在不久的从前(也还是要以年为单位哈), 我们如果需要调试第三方代码, 或者框架代码很麻烦. 需要配置symbols, 匹配原始代码路径等. 为此, MS推出了 Source Link 功能, ...
- 资源:HTML调色板
调色板路径 https://encycolorpedia.cn/
- bugku秋名山车神
不断的刷新,发现表达式一直在变换,这种必须写脚本,才能跟上速度.直接上代码 import re import requests s=requests.session() r=s.get("h ...
- STM32中的通信协议
按照数据传送方式分: 串行通信(一条数据线.适合远距离传输)并行通信(多条数据线.成本高.抗干扰性差) 按照通信的数据同步方式分: 异步通信(以1个字符为1帧.发送与接收时钟不一致)同步通信(位同步. ...
- Min25 筛与 Powerful Numbers
Min25 筛与 Powerful Numbers Min25 筛 大喊一声 Min25 NB!!! 这是一个非常神奇的东西,用于求更加普遍的积性函数的前缀和. 比如我们要求 \(\sum_{i=1} ...
- C语言:字符型数据(常量)
字符型数据就是字符. 字符型数据的表示 字符型数据是用单引号括起来的一个字符.例如:'a'.'b'.'='.'+'.'?'都是合法字符型数据.在C语言中,字符型数据有以下特点: 字符型数据只能用单引号 ...
- C语言:数的保存 原码 反码 补码
a=6 a=-18 a 的原码就是0000 0000 0000 0110 1000 0000 0001 0010 ...