生产者与消费者问题JUC
生产者与消费者问题
Synchronized版
package com.cz.demo1;
/**
* @author 卓亦苇
* @version 1.0
* 2023/3/2 9:55
*/
public class TestConsumer {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.increment();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.decrement();
}
},"B").start();
}
}
class Data{
private int num = 0;
public synchronized void increment(){
if (num!=0){
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName()+"生产了"+num);
num++;
this.notifyAll();
}
public synchronized void decrement(){
if (num==0) {
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName() + "消费了" + num);
num--;
this.notifyAll();
}
}
问题存在,多个线程状态下是否安全?
存在虚假唤醒
if改为while
package com.cz.demo1;
/**
* @author 卓亦苇
* @version 1.0
* 2023/3/2 9:55
*/
public class TestConsumer {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.increment();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.increment();
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
data.decrement();
}
},"B").start();
}
}
class Data{
private int num = 0;
public synchronized void increment(){
while (num!=0){
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName()+"生产了"+num);
num++;
this.notifyAll();
}
public synchronized void decrement(){
while (num==0) {
try {
this.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(Thread.currentThread().getName() + "消费了" + num);
num--;
this.notifyAll();
}
}
JUC版的生产者与消费者问题
package com.cz.demo1;
/**
* @author 卓亦苇
* @version 1.0
* 2023/3/3 9:14
*/
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* JUC版本生产者与消费者问题,利用Lock锁来实现
*/
public class TestConsumer2 {
public static void main(String[] args) {
Date2 date2 = new Date2();
new Thread(()->{
for (int i = 0; i < 10; i++) {
date2.increment();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
date2.decrement();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
date2.increment();
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
date2.decrement();
}
},"D").start();
}
}
class Date2{
private int num = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
public void increment(){
lock.lock();
try {
while (num!=0) {
condition.await();
}
num++;
System.out.println(Thread.currentThread().getName() + "生产了" + num);
condition.signalAll();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
public void decrement(){
lock.lock();
try {
while (num==0) {
condition.await();
}
num--;
System.out.println(Thread.currentThread().getName() + "消费了" + num);
condition.signalAll();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}
condition优势
可以精准通知和唤醒线程
原来的线程执行时由CPU自行调度,利用condition可以精准通知和唤醒线程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类