虚假唤醒
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Seller seller = new Seller();
Productor productor = new Productor(seller);
Consumer consumer = new Consumer(seller);
new Thread(productor, "生产者A").start();
new Thread(consumer, "消费者B").start();
new Thread(productor, "生产者C").start();
new Thread(consumer, "消费者D").start();
}
}
// 销售员
class Seller {
private int product = 0;
// 进货
public synchronized void get() {
if (product >= 1) {
System.out.println("货物已满");
try {
// 对应Object中的 wait()
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " : " + ++product);
// 对应Object中的notifyAll()
this.notifyAll();
}
// 销售
public synchronized void sale() {
if (product <= 0) {
System.out.println("货物卖完");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " : " + --product);
this.notifyAll();
}
}
// 生产者
class Productor implements Runnable {
private Seller seller;
public Productor(Seller seller) {
this.seller = seller;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
seller.get();
}
}
}
class Consumer implements Runnable {
private Seller seller;
public Consumer(Seller seller) {
this.seller = seller;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
seller.sale();
}
}
}
解决虚假唤醒
对于Object.wait()方法,JDK开发文档是这样说的
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop(对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用):
synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition }
一、使用synchronized关键字
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Seller seller = new Seller();
Productor productor = new Productor(seller);
Consumer consumer = new Consumer(seller);
new Thread(productor, "生产者A").start();
new Thread(consumer, "消费者B").start();
new Thread(productor, "生产者C").start();
new Thread(consumer, "消费者D").start();
}
}
// 销售员
class Seller {
private int product = 0;
// 进货
public synchronized void get() {
while (product >= 1) {
System.out.println("货物已满");
try {
this.wait(); // wait()方法应该总是使用在while里面可以防止虚假唤醒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " : " + ++product);
this.notifyAll();
}
// 销售
public synchronized void sale() {
while (product <= 0) {
System.out.println("货物卖完");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " : " + --product);
this.notifyAll();
}
}
// 生产者
class Productor implements Runnable {
private Seller seller;
public Productor(Seller seller) {
this.seller = seller;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
seller.get();
}
}
}
class Consumer implements Runnable {
private Seller seller;
public Consumer(Seller seller) {
this.seller = seller;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
seller.sale();
}
}
}
二、使用同步锁
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Seller seller = new Seller();
Productor productor = new Productor(seller);
Consumer consumer = new Consumer(seller);
new Thread(productor, "生产者A").start();
new Thread(consumer, "消费者B").start();
new Thread(productor, "生产者C").start();
new Thread(consumer, "消费者D").start();
}
}
// 销售员
class Seller {
private int product = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
// 进货
public void get() {
lock.lock();
try {
while (product >= 1) {
System.out.println("货物已满");
try {
// 对应Object中的 wait()
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " : " + ++product);
// 对应Object中的notifyAll()
condition.signalAll();
} finally {
lock.unlock();
}
}
// 销售
public synchronized void sale() {
lock.lock();
try {
while (product <= 0) {
System.out.println("货物卖完");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " : " + --product);
condition.signalAll();
} finally {
lock.unlock();
}
}
}
// 生产者
class Productor implements Runnable {
private Seller seller;
public Productor(Seller seller) {
this.seller = seller;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
seller.get();
}
}
}
class Consumer implements Runnable {
private Seller seller;
public Consumer(Seller seller) {
this.seller = seller;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
seller.sale();
}
}
}