生产者消费者问题
/**
* 线程之间的通信问题:生产者和消费者问题! 等待唤醒,通知唤醒
* 线程交替执行 A B 操作同一个变量 num = 0
* A num+1
* B num-1
*/
public class A {
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.increment();
} 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 number = 0;
//+1
public synchronized void increment() throws InterruptedException {
/*
* 使用while 而不是if的原因:
* 使用if会存在虚假唤醒的情况。
* 所谓虚假唤醒是指当前线程被唤醒了,但是if已经执行完了,它不会再次执行,
* 就不能执行if内的代码即假唤醒。
*/
while (number!=0){ //0
// 等待
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
// 通知其他线程,我+1完毕了
this.notifyAll();
}
//-1
public synchronized void decrement() throws InterruptedException {
while (number==0){ // 1
// 等待
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
// 通知其他线程,我-1完毕了
this.notifyAll();
}
}
使用JUC解决生产者消费者问题
在Lock 中由如下描述
关于Condition描述如下
class BoundedBuffer {
final Lock lock = new ReentrantLock();
//用lock.newCondition获得condition
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally { lock.unlock(); }
}
public Object take() throws InterruptedException {
lock.lock(); try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally { lock.unlock(); }
}
}
使用上面的代码实现生产者消费者
public class B {
public static void main(String[] args) {
Data2 data = new Data2();
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.increment();
} 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 Data2{ // 数字 资源类
private int number = 0;
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//condition.await(); // 等待
//condition.signalAll(); // 唤醒全部
//+1
public void increment() throws InterruptedException {
lock.lock();
try {
// 业务代码
while (number!=0){ //0
// 等待
condition.await();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
// 通知其他线程,我+1完毕了
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//-1
public synchronized void decrement() throws InterruptedException {
lock.lock();
try {
while (number==0){ // 1
// 等待
condition.await();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
// 通知其他线程,我-1完毕了
condition.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
运行效果:
Condition 精准的通知和唤醒线程
/**
* A 执行完调用B,B执行完调用C,C执行完调用A
*/
public class C {
public static void main(String[] args) {
Data3 data = new Data3();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.printA();
}
},"A").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.printB();
}
},"B").start();
new Thread(()->{
for (int i = 0; i <10 ; i++) {
data.printC();
}
},"C").start();
}
}
class Data3{ // 资源类 Lock
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
private int number = 1; // 1A 2B 3C
public void printA(){
lock.lock();
try {
// 业务,判断-> 执行-> 通知
while (number!=1){
// 等待
condition1.await();
}
System.out.println(Thread.currentThread().getName()+"=>AAAAAAA");
// 唤醒,唤醒指定的人,B
number = 2;
condition2.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printB(){
lock.lock();
try {
// 业务,判断-> 执行-> 通知
while (number!=2){
condition2.await();
}
System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
// 唤醒,唤醒指定的人,c
number = 3;
condition3.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void printC(){
lock.lock();
try {
// 业务,判断-> 执行-> 通知
// 业务,判断-> 执行-> 通知
while (number!=3){
condition3.await();
}
System.out.println(Thread.currentThread().getName()+"=>BBBBBBBBB");
// 唤醒,唤醒指定的人,c
number = 1;
condition1.signal();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
视频参考https://www.bilibili.com/video/BV1B7411L7tE
上一篇:Lock锁
下一篇:8锁问题