生产者与消费者
Synchronized版本
package com.nie.juc.shxf;/*
*
*@auth wenzhao
*@date 2021/4/20 13:15
*/
/**
* 生产者消费者
*/
public class Demo01 {
public static void main(String[] args) {
Data data = new Data();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
}
}
//判断等待 业务通知
class Data {
//数字资源
private int number = 0;
//资源加一 increment增加
//生产者
public synchronized void increment() throws InterruptedException {
if (number != 0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "===>" + number);
//通知其他等待的线程
this.notifyAll();
}
//资源加一 decrement 递减
//消费者
public synchronized void decrement() throws InterruptedException {
if (number == 0) {
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "===>" + number);
//通知其他等待的线程
this.notifyAll();
}
}
问题存在: 如果abcd 4个线程! 虚假唤醒
虚假唤醒相关解释
if改为while判断
package com.nie.juc.shxf;/*
*
*@auth wenzhao
*@date 2021/4/20 13:15
*/
/**
* 生产者消费者
*/
public class Demo02 {
public static void main(String[] args) {
Data2 data = new Data2();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
//判断等待 业务通知
class Data2 {
//数字资源
private int number = 0;
//资源加一 increment增加
//生产者
public synchronized void increment() throws InterruptedException {
while (number != 0) {
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName() + "===>" + number);
//通知其他等待的线程
this.notifyAll();
}
//资源加一 decrement 递减
//消费者
public synchronized void decrement() throws InterruptedException {
while (number == 0) {
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName() + "===>" + number);
//通知其他等待的线程
this.notifyAll();
}
}
结果
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
B===>0
A===>1
C===>0
A===>1
B===>0
A===>1
D===>0
A===>1
C===>0
A===>1
D===>0
A===>1
B===>0
A===>1
D===>0
A===>1
C===>0
A===>1
D===>0
JUC版的生产者和消费者问题
通过Lock找到Condition
代码实现
package com.nie.juc.shxf;/*
*
*@auth wenzhao
*@date 2021/4/20 13:15
*/
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 生产者消费者
*/
public class JUCDemo03 {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "D").start();
}
}
//判断等待 业务通知
class Data3 {
//数字资源
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//condition.await(); 等待
//condition.signalAll();; 唤醒全部
//资源加一 increment增加
//生产者
public void increment() throws InterruptedException {
lock.lock(); //开启锁
try {
while (number != 0) {
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName() + "=增加=>>" + number);
condition.signalAll();//唤醒其他程序 我生产者已经执行完毕
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//资源加一 decrement 递减
//消费者
public void decrement() throws InterruptedException {
lock.lock(); //开启锁
try {
while (number == 0) {
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName() + "=减少=>>" + number);
condition.signalAll();//唤醒其他程序 我生产者已经执行完毕
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
结果
A=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
B=减少=>>0
C=增加=>>1
D=减少=>>0
A=增加=>>1
D=减少=>>0
A=增加=>>1
D=减少=>>0
A=增加=>>1
D=减少=>>0
A=增加=>>1
D=减少=>>0
A=增加=>>1
D=减少=>>0
A=增加=>>1
D=减少=>>0
A=增加=>>1
.....
后续一切正常
补充Condition
condition 精准的通知和唤醒线程
有序的执行ABCD
Reentrant
再进入
ReentrantLock
condition2.await(); 等待 condition1.signal();//唤醒其他人
package com.nie.juc.shxf;/*
*
*@auth wenzhao
*@date 2021/4/20 13:15
*/
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 有序的打印ABC
*/
public class JUCDemo04Order {
public static void main(String[] args) {
Data4 data = new Data4();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.print1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.print2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
new Thread(() -> {
for (int i = 0; i < 20; i++) {
try {
data.print3();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "C").start();
}
}
//判断等待 业务通知
class Data4 {
//数字资源
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();
private int number = 1; //1A 2B 3C
//condition.await(); 等待
//condition.signalAll();; 唤醒全部
//资源加一 increment增加
//生产者
public void print1() throws InterruptedException {
lock.lock(); //开启锁
try {
while (number != 1) {
condition1.await();
}
System.out.println(Thread.currentThread().getName() +"AAAAAA");
number = 2;
condition2.signal();//唤醒其他人2 号
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//资源加一 decrement 递减
//消费者
public void print2() throws InterruptedException {
lock.lock(); //开启锁
try {
while (number != 2) {
condition2.await();
}
System.out.println(Thread.currentThread().getName() + "BBBBB");
number=3;
condition3.signal();//唤醒其他人 3 号
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//资源加一 decrement 递减
//消费者
public void print3() throws InterruptedException {
lock.lock(); //开启锁
try {
while (number != 3) {
condition3.await();
}
System.out.println(Thread.currentThread().getName() +"CCCCC");
number=1;
condition1.signal();//唤醒其他人 1 号
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}