先定义资源类 :包含资源数量,消费方法,生产方法
当资源为0时,生产者生产资源
当资源为1时,消费者消费资源
//定义Resource作为线程需要的资源
public class Resource {
//当前资源的数量
int num=0;
//当前资源的上限
int size=1;
//消费资源
public synchronized void remove(){
if(num==0){
try {
System.out.println("消费者等待");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num--;
System.out.println("消费者线程为:"+Thread.currentThread().getName()+"资源数量"+num);
notifyAll();
}
//生产资源
public synchronized void put(){
if(num==size){
try {
System.out.println("生产者等待");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
num++;
System.out.println("生产者线程为:"+Thread.currentThread().getName()+"资源数量"+num);
notifyAll();
}
}
创建消费者线程
//定义Consumer使用remove消费资源
public class Consumer implements Runnable {
private Resource resource;
public Consumer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for(int i=0;i<10;i++){
resource.remove();
}
}
}
创建生产者线程
//定义Producer使用put生产资源
public class Producer implements Runnable {
private Resource resource;
public Producer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
for(int i=0;i<10;i++){
resource.put();
}
}
}
执行线程
public static void main(String[] args) {
Resource resource = new Resource();
Consumer consumer = new Consumer(resource);
Producer producer = new Producer(resource);
new Thread(consumer).start();
new Thread(producer).start();
}
可以发现:线程执行情况正常
但是当我们分别有两个消费者和生产者时,线程执行就出现了异常
public static void main(String[] args) {
Resource resource = new Resource();
Consumer consumer = new Consumer(resource);
Producer producer = new Producer(resource);
new Thread(producer,"生产者1").start();
new Thread(producer,"生产者2").start();
new Thread(consumer,"消费者1").start();
new Thread(consumer,"消费者2").start();
}
这就是虚假唤醒问题
当我们的线程执行了start
,此时线程都进入就绪状态
生产者1获取cpu执行权,变为运行状态,执行其中run
方法,资源数+1
接着生产者1和生产者2先后获取cpu执行权,因为资源数为1,线程阻塞
消费者获取cpu执行权,资源数-1,并且会唤醒阻塞的线程
这时候就变成最初的状态
当生产者再次执行,是从刚才阻塞的地方继续运行,就不用再判断资源的数量是否为0了
出现虚假唤醒的原因是从阻塞态到就绪态再到运行态没有进行判断
我们可以每次得到操作权时都进行判断,将if
判断改成while
判断即可
此时执行情况正常