生产者与消费者问题是面试的常考题,并且经常让手撕代码
生产者消费者本质其实就是两个对象同时操作同一个变量,此时如果是多线程,就必须要加锁,防止线程之间的相互影响,以下是代码:
创建一个 ticket 对象,有添加和减少的方法,对应着生产和消费,然后 new 两个线程去分别调用两个方法,为了防止线程冲突,方法 使用 synchornized 修饰。
public class MyThread {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
try {
ticket.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "A").start();
new Thread(() -> {
for (int i = 0; i < 40; i++) {
try {
ticket.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "B").start();
}
}
class Ticket {
private int number = 0;
public synchronized void increment() throws InterruptedException {
if (number != 0) {
this.wait();//生产者,如果不是 0,等待
}//如果是零,开始生产,同时通知其他所有线程
number++;
System.out.println(Thread.currentThread().getName() + " " + number);
this.notifyAll();
}
public synchronized void decrement() throws InterruptedException {
if (number == 0) {
this.wait();//消费者同理
}
number--;
System.out.println(Thread.currentThread().getName() + " " + number);
this.notifyAll();
}
}
运行代码看结果:
齐刷刷的 1-0 交替,仿佛是完成了代码,但是面试官看到这样的代码一定直摇头,他会说,如果你再创建几个线程呢?
那就再开俩线程测试一下呗:
运行代码发现:
这是什么东西,怎么回事?
打开 API 文档,找到 Object 类的 wait 方法
线程可以背唤醒,而不会接通知,中断或者超时,即所谓的 虚假唤醒,原因是我们使用 if 来判断条件,但是等待应该总是出现在循环中,所以,修改代码
把 if 修改为 while,再次运行的结果:
没有任何问题,1,0 交替出现,完成生产者消费者问题



