并发编程之生产者和消费者问题
2023-09-27 14:26:42 时间
简单的线程通信,一个线程对数字进行增加操作、另一个线程对线程进行减少操作。
简单解释:线程A对数字进行减少操作,但不会一直让这个数字减少下去。当减少到设定的条件,让其等待,通知其他线程获得该资源。
package com.ProductAndCustomer;
/**
* 线程之间的通信,生产者和消费者问题
*/
public class Product {
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();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
}
}
//等待,业务,通知
class Data{
//资源类
private int num = 0;
//增加操作
public synchronized void increment() throws InterruptedException {
if(num != 0){
//等待
this.wait();
}
num ++;
System.out.println(Thread.currentThread().getName()+"=>"+num);
//通知其他线程,+1结束
this.notifyAll();
}
//减少操作
public synchronized void decrement() throws InterruptedException {
if(num == 0){
//等待
this.wait();
}
num --;
System.out.println(Thread.currentThread().getName()+"=>"+num);
//通知其他线程,-1结束
this.notifyAll();
}
}
测试
在多几个线程
package com.ProductAndCustomer;
/**
* 线程之间的通信,生产者和消费者问题
*/
public class Product {
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();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 10; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//等待,业务,通知
class Data{
//资源类
private int num = 0;
//增加操作
public synchronized void increment() throws InterruptedException {
if(num != 0){
//等待
this.wait();
}
num ++;
System.out.println(Thread.currentThread().getName()+"=>"+num);
//通知其他线程,+1结束
this.notifyAll();
}
//减少操作
public synchronized void decrement() throws InterruptedException {
if(num == 0){
//等待
this.wait();
}
num --;
System.out.println(Thread.currentThread().getName()+"=>"+num);
//通知其他线程,-1结束
this.notifyAll();
}
}
测试结果
这里会出现虚假唤醒
查看开发文档可知、需要修改判断语句 if修改为while
修改后的代码
package com.ProductAndCustomer;
/**
* 线程之间的通信,生产者和消费者问题
*/
public class Product {
public static void main(String[] args) {
Data data = new Data();
new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"C").start();
new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"D").start();
}
}
//等待,业务,通知
class Data{
//资源类
private int num = 0;
//增加操作
public synchronized void increment() throws InterruptedException {
while(num != 0){
//等待
this.wait();
}
num ++;
System.out.println(Thread.currentThread().getName()+"=>"+num);
//通知其他线程,+1结束
this.notifyAll();
}
//减少操作
public synchronized void decrement() throws InterruptedException {
while(num == 0){
//等待
this.wait();
}
num --;
System.out.println(Thread.currentThread().getName()+"=>"+num);
//通知其他线程,-1结束
this.notifyAll();
}
}
测试结果
相关文章
- 【并发编程神器】,Worker Thread模式
- 【并发编程】史上最详细的ReentrantReadWriteLock源码刨析
- 【并发编程】ReentrantLock的lock()方法源码分析
- 解密诡异并发问题的幕后黑手:可见性问题
- 【Linux开发】linux设备驱动归纳总结(四):5.多处理器下的竞态和并发
- 浅谈Java并发编程系列(二)—— Java内存模型
- 那一定都是你的错!- 一次FastDFS并发问题的排查经历
- 并发编程(八)—— Java 并发队列 BlockingQueue 实现之 ArrayBlockingQueue 源码分析
- 并发编程(五)——AbstractQueuedSynchronizer 之 ReentrantLock源码分析
- Python Web学习笔记之并发编程的孤儿进程与僵尸进程
- 马士兵老师高并发编程同步容器
- 并发数 / 响应时间 / 吞吐量 计算公式
- Java高并发专题之4、JMM相关的一些概念
- 流畅的python第十七章使用期物处理并发
- java-并发-ConcurrentHashMap高并发机制-jdk1.6
- 3高并发server:多路IO之epoll
- 使用 channel 控制并发数量
- 【并发编程六】c++进程通信——信号量(semaphore)
- Android并发编程之图文解析volatile关键字
- 蜕变成蝶~Linux设备驱动中的并发控制
- 【并发编程038】什么是适应性自旋?和普通自旋的区别?
- 【并发编程037】由用户态切换到内核态的步骤?
- 【并发编程008】调用共享对象的notify()方法后, 会唤醒一个在该共享变量上调用wait()的线程, 说说两个线程对锁的获取释放过程?
- 【并发编程-002】为何要将程序计数器设置为线程私有的?