标签:消费 this 商品 lambda 生产 == exce com ack
当一个条件满足时,很多线程都被唤醒了,但是只有其中部分是有用的唤醒,其它的唤醒都是无用功;
比如买货:如果商品本来没有货物,突然进了一件商品,这是所有的线程都被唤醒了,但是只能一个人买,所以其他人都是假唤醒,获取不到对象的锁;
避免虚假唤醒的示例:这里使用了 Lambda 表达式
package com.jia.pc; 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 (number != 0){ // 等待 this.wait(); } number++; System.out.println(Thread.currentThread().getName() + "->" + number); // 通知其他线程,我+1完毕 this.notifyAll(); } // -1 public synchronized void decrement() throws InterruptedException { while (number == 0){ // 等待 this.wait(); } number--; System.out.println(Thread.currentThread().getName() + "->" + number); // 通知其他线程,我-1完毕 this.notifyAll(); } }
运行结果:
A->1 B->0 A->1 B->0 A->1 B->0 A->1 B->0 A->1 B->0 A->1 B->0 A->1 B->0 A->1 B->0 A->1 B->0 A->1 B->0 C->1 D->0 C->1 D->0 C->1 D->0 C->1 D->0 C->1 D->0 C->1 D->0 C->1 D->0 C->1 D->0 C->1 D->0 C->1 D->0 Process finished with exit code 0
把 while (number != 0) {}
换成 if (number == 0) {}
就会出现虚假唤醒
1. 因为if只会执行一次,执行完会接着向下执行if()外边的
2. 而while不会,直到条件满足才会向下执行while()外边的
标签:消费 this 商品 lambda 生产 == exce com ack
原文地址:https://www.cnblogs.com/luckyjcx/p/12638105.html