生产者,消费者问题的理解

问题

  • 生产者和消费者本质上就是两者的先后问题,一定要先生产了,才能进行消费。如果消费资源没有,就一定要先生产才能继续消费。

思路

  • 两个线程类,通过构造方法传入对象实现资源共享,还有一个测试类。
  • 两个线程首先用同一个对象的对象锁实现线程安全。
  • 接着用判断,然后用共享对象调用wait()方法,用共享对象调用notify方法实现生产者消费者。

  • list.wait方法,调用的线程会阻塞在调用wait方法的对象上(也就是list),一直到被notify唤醒才重新拥有抢对象锁的权力。
  • list.notify方法,会唤醒阻塞在调用该方法的对象上的线程(list上的线程),但是该方法不会让当前线程放弃锁,只是让处于等待状态的线程变回就绪状态(可抢锁状态),而且一直到拥有锁的线程释放锁之后,释放锁的线程还是有可能又抢到锁的。

代码

生产者

package consumer;
import java.util.List;
public class Producer implements Runnable {
    private List list;

    public Producer() {
    }

    public Producer(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true) {

            synchronized (list) {
                System.out.println("生产者抢到了锁");
                if (list.size() > 0) {//已经有产品了就等待消费者消费
                    try {
                        System.out.println("生产者在等待");
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.add("1");
                System.out.println("生产者生产了!");
                list.notifyAll();
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

消费者

package consumer;

import java.util.List;

public class Consumer implements Runnable {
    List list;

    public Consumer() {
    }

    public Consumer(List list) {
        this.list = list;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (list) {
                System.out.println("消费者抢到了锁");
                if (list.size() == 0) {//没有产品就等待
                    try {
                        System.out.println("消费者在等待");
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                list.remove(0);
                System.out.println("消费者消费了!");
                list.notifyAll();
            }
            try {
                Thread.sleep(1000*2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


测试类

package consumer;
import java.util.ArrayList;
import java.util.List;
public class ConsumeTest {
    public static void main(String[] args) {
//    创建仓库
        List list = new ArrayList();//只能最多只能有一个元素
        Thread t1 = new Thread(new Consumer(list));
        Thread t2 = new Thread(new Producer(list));
        t1.start();
        t2.start();
        
    }

}

结论:

结论:

  • 每一次运行遇到共享对象.wait,线程就进入阻塞在共享对象上,线程会释放持有的锁,然后其他线程就可以获得该锁。
  • 当其他线程调用共享对象.notify,在该共享对象上等待的线程会被唤醒,并重新进入就绪状态,可以抢锁,但不代表就一定能抢到;
  • 而如果抢到了锁,线程就会从wait方法的下一行开始继续执行(也就是之前阻塞在哪,就从哪开始进行执行)。

调用wait,notify方法的对象一定是多线程共享的对象才能达到生产者消费者彼此等待的效果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值