JUC 并发编程--02,生产者和消费者 synchronized的写法 , juc的写法. Condition的用法
synchronized的写法
class PCdemo{
public static void main(String[] args) {
//多个线程操作同一资源
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-1").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-2").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-3").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-4").start();
}
}
//这是一个资源类,
class Data {
private int num = 0;
//加1
public synchronized void increment() throws InterruptedException {
while(num != 0){
this.wait();
}
num++;
System.out.println("当前线程名字:" + Thread.currentThread().getName() + "加1 操作, num为" + num);
this.notifyAll();
}
//减1
public synchronized void decrement() throws InterruptedException {
while(num == 0){
this.wait();
}
num--;
System.out.println("当前线程名字:" + Thread.currentThread().getName() + "减1 操作, num为" + num);
this.notifyAll();
}
}
结果:
这里需要注意一个概念: 虚假唤醒,就是说线程被唤醒了, 但不会被通知 如果把资源类Data中的 increment, decrement方法中的while 换为: if, 那么运行的时候, 二个线程的结果是正常的, 如果二个以上就会出错,结果为
JUC 版本的 生产者和消费者问题
public class JucPCdemo {
public static void main(String[] args) {
//JUC 版本的 就是来替代 synchronized版本的
DataJ data = new DataJ();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-1").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-2").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-3").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-4").start();
}
}
class DataJ{
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
private int num = 0;
//加1
public void increment() throws InterruptedException {
//先加锁
lock.lock();
try {
while(num != 0){
condition.await();//这个替代 this.wait()
}
num++;
System.out.println("当前线程名字:" + Thread.currentThread().getName() + "加1 操作, num为" + num);
condition.signalAll();// 这个来替代 this.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
//减1
public void decrement() throws InterruptedException {
//先加锁
lock.lock();
try {
while(num == 0){
condition.await();//这个替代 this.wait();
}
num--;
System.out.println("当前线程名字:" + Thread.currentThread().getName() + "减1 操作, num为" + num);
condition.signalAll();// 这个来替代 this.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
}
结果同样是正确的
然而 Condition 更强大的是精确通知和精确唤醒, 之前的运行结果线程之间是随机运行的,如果让线程 1,2,3,4 依次循环有序执行, 就要用到Condition
public class JucPCdemo01 {
public static void main(String[] args) {
//JUC 版本的 就是来替代 synchronized版本的
//4个线程依次循环有序执行, num 初始值为0, 线程1--A, 线程2--B, 线程3--C, 线程4--D
DataC data = new DataC();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.printA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-1").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.printB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-2").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.printC();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-3").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.printD();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"thread-4").start();
}
}
class DataC{
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();//对应A
private Condition condition2 = lock.newCondition();//对应B
private Condition condition3 = lock.newCondition();//对应C
private Condition condition4 = lock.newCondition();//对应D
private String str = "A";
public void printA() throws InterruptedException {
//先加锁
lock.lock();
try {
while(! "A".equals(str)){
condition1.await();//只要不是 A 就等待
}
System.out.println("当前线程名字:" + Thread.currentThread().getName() + "对应str为" + str);
str = "B";
condition2.signal();//这里指定唤醒 线程2 对应B
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
public void printB() throws InterruptedException {
//先加锁
lock.lock();
try {
while(!"B".equals(str)){
condition2.await();//只要不是B 就等待
}
System.out.println("当前线程名字:" + Thread.currentThread().getName() + "对应str为" + str);
str = "C";
condition3.signal();//这里指定唤醒 线程3 对应C
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
public void printC() throws InterruptedException {
//先加锁
lock.lock();
try {
while(! "C".equals(str)){
condition3.await();//只要不是C 就等待
}
System.out.println("当前线程名字:" + Thread.currentThread().getName() + "对应str为" + str);
str = "D";
condition4.signal();//这里指定唤醒 线程4 对应D
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
public void printD() throws InterruptedException {
//先加锁
lock.lock();
try {
while(! "D".equals(str)){
condition4.await();//只要不是D 就等待
}
System.out.println("当前线程名字:" + Thread.currentThread().getName() + "对应str为" + str);
str = "A";
condition1.signal();//这里指定唤醒 线程1 对应A
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//释放锁
lock.unlock();
}
}
}
运行结果为;
JUC 并发编程--02,生产者和消费者 synchronized的写法 , juc的写法. Condition的用法的更多相关文章
- Java并发编程(4)--生产者与消费者模式介绍
一.前言 这种模式在生活是最常见的,那么它的场景是什么样的呢? 下面是我假象的,假设有一个仓库,仓库有一个生产者和一个消费者,消费者过来消费的时候会检测仓库中是否有库存,如果没有了则等待生产,如果有就 ...
- JUC 并发编程--01,线程,进程,经典卖票案例, juc的写法
进程: 就是一个程序, 里面包含多个线程, 比如一个QQ程序 线程: 进程中最小的调度单元, 比如 QQ中的自动保存功能 并发: 多个线程操作同一资源, 抢夺一个cpu的执行片段, 快速交替 并行: ...
- 并发编程 02—— ConcurrentHashMap
Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...
- JUC并发编程学习笔记
JUC并发编程学习笔记 狂神JUC并发编程 总的来说还可以,学到一些新知识,但很多是学过的了,深入的部分不多. 线程与进程 进程:一个程序,程序的集合,比如一个音乐播发器,QQ程序等.一个进程往往包含 ...
- JUC并发编程与高性能内存队列disruptor实战-上
JUC并发实战 Synchonized与Lock 区别 Synchronized是Java的关键字,由JVM层面实现的,Lock是一个接口,有实现类,由JDK实现. Synchronized无法获取锁 ...
- 并发编程的锁机制:synchronized和lock
1. 锁的种类 锁的种类有很多,包括:自旋锁.自旋锁的其他种类.阻塞锁.可重入锁.读写锁.互斥锁.悲观锁.乐观锁.公平锁.可重入锁等等,其余就不列出了.我们重点看如下几种:可重入锁.读写锁.可中断锁. ...
- JUC并发编程基石AQS之主流程源码解析
前言 由于AQS的源码太过凝练,而且有很多分支比如取消排队.等待条件等,如果把所有的分支在一篇文章的写完可能会看懵,所以这篇文章主要是从正常流程先走一遍,重点不在取消排队等分支,之后会专门写一篇取消排 ...
- python并发编程02 /多进程、进程的创建、进程PID、join方法、进程对象属性、守护进程
python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 目录 python并发编程02 /多进程.进程的创建.进程PID.join方法.进程对象属性.守护进程 ...
- python 并发编程 多进程 生产者消费者模型介绍
一 生产者消费者模型介绍 为什么要使用生产者消费者模型 生产者指的是生产数据的任务,消费者指的是处理数据的任务, 生产数据目的,是为了给消费者处理. 在并发编程中,如果生产者处理速度很快,而消费者处理 ...
随机推荐
- Average Score39届亚洲赛牡丹江站A题
题意: A班有n个人,B班有m个人,然后现在给你n-1个A班人的成绩,和m个B班人的成绩,然后题目要求求出A班剩下的没给成绩那个人的成绩范围,要求是这个人从A班转到B班后能使A,B的平均分 ...
- Python中的Pandas模块
目录 Pandas Series 序列的创建 序列的读取 DataFrame DataFrame的创建 DataFrame数据的读取 Panel Panel的创建 Pandas Pandas ( Py ...
- POJ1135比较有意思的对短路(多米骨牌)
题意: 有一个骨牌游戏,就是推到一个后所有的牌都会被退到的那种游戏,起点是1,有两种骨牌,一种是关键牌,另一种是普通牌,普通牌是连接关键牌用的,给你一些边a b c的意思是关键牌a倒之后c时 ...
- flex布局的使用
一.Flex布局是什么? Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性. 任何一个容器都可以指定为Flex布局. .box{ disp ...
- Base64文件上传(Use C#)
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,它是一种基于64个可打印字符来表示二进制数据的方法. 使用base64进行文件上传的具体流程是:前台使用js将文件转换为base64格 ...
- JAVA并发(1)-AQS(亿点细节)
AQS(AbstractQueuedSynchronizer), 可以说的夸张点,并发包中的几乎所有类都是基于AQS的. 一起揭开AQS的面纱 1. 介绍 为依赖 FIFO阻塞队列 的阻塞锁和相关同步 ...
- 目录和文件 按创建时间排序du -h --time --max-depth=1 . |sort -r -t $'\t' -k 2 Linux查看文件夹大小,并按文件夹创建时间排序
目录和文件 按创建时间排序 # du -h --time --max-depth=1 . |sort -r -t $'\t' -k 230M 2020-04-01 14:54 .28K 2020-04 ...
- iPhone手机怎么和电脑互传文件,一条数据线搞定
官方的方法是,通过iTunes进行文件的传输.传个文件还要特意安装个iTunes,实在是麻烦. 其实我们只需要在苹果应用商店app store下载Documents这个文件就可以. 另外,Docume ...
- python基础之psutil模块和发邮件(smtplib和yagmail)
除了内建的模块外,Python还有大量的第三方模块. 基本上,所有的第三方模块都会在PyPI - the Python Package Index上注册,只要找到对应的模块名字,即可用pip安装. 此 ...
- Python数模笔记-PuLP库(1)线性规划入门
1.什么是线性规划 线性规划(Linear programming),在线性等式或不等式约束条件下求解线性目标函数的极值问题,常用于解决资源分配.生产调度和混合问题.例如: max fx = 2*x1 ...