Synchronized与ReentrantrantLock实现生产者消费者模式

synchronized与ReentranLock
wait(),notify()方法只能在synchronized代码块中使用,底层是通过对象头中得锁监视器也就是说这是对象Object方法,一旦用了wait(),notify()方法那么这个synchronied就是重量级锁,wait(),notify()方法是是否锁监视器中得WaitSet 

在使用synchronized 时 线程通信通过wait() notify()方法  假如在生产者消费者模式下 通过wait() notify()方法唤醒线程 是很不好的 
例如 如果 生产者往厂库已经塞满了 生产者线程 进入EntrySet等待队列等待 而如果消费者线程也消费完进入等待队列 此时调用notify方法你不能指定唤醒的是哪一个线程 假如我需要生产者 却唤醒了消费者 即使是notifyAll 此时场景没必要唤醒消费者 

因此 JUC 产生了因为synchronized 对象锁只有一个休息室  ReentrantrantLock 注意点 lock方法与unlock方法需要连用 最好使用try finally块 避免错误异常 锁未完全释放导致死锁
ReentrantrantLock锁更细腻  因为ReentrantLock提供了休息室condition(本质就是队列)  在生产者消费者模式下 可以 生产者进入生产者休息室 消费者进入消费者休息室 因此在需要生产者是只要去生产者休息室进行唤醒即可 消费者同理 
调用 condition.signal() condition.await()
因此使用ReentrantLock解决生产者消费者问题 需要两个condition

synchronized实现生产者消费者模式
import java.util.LinkedList;

class ProducerConsumer {
    private LinkedList<Integer> buffer = new LinkedList<>();
    private int capacity = 5;

    public void produce() {
        synchronized (this) {
            while (buffer.size() == capacity) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int value = (int) (Math.random() * 100);
            buffer.add(value);
            System.out.println("Produced: " + value);
            notifyAll();
        }
    }

    public void consume() {
        synchronized (this) {
            while (buffer.isEmpty()) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int value = buffer.removeFirst();
            System.out.println("Consumed: " + value);
            notifyAll();
        }
    }
}

public class Main {
    public static void main(String[] args) {
        ProducerConsumer pc = new ProducerConsumer();

        Thread producerThread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                pc.produce();
            }
        });

        Thread consumerThread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                pc.consume();
            }
        });

        producerThread.start();
        consumerThread.start();
    }
}
ReentrantLock实现生产者消费者模式
import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

// 生产者消费者模式的实现类
class ProducerConsumer {
    private LinkedList<Integer> buffer = new LinkedList<>(); // 缓冲区
    private int capacity = 5; // 缓冲区容量
    private Lock lock = new ReentrantLock(); // 锁对象
    private Condition pro = lock.newCondition(); // 生产休息室
    private Condition csu= lock.newCondition(); // 消费休息室

    // 生产者方法
    public void produce() {
        lock.lock(); // 加锁
        try {
            while (buffer.size() == capacity) { // 缓冲区已满时
                try {
                    pro.await(); //  停止生产 让生产线程进入休息室
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int value = (int) (Math.random() * 100); // 生产一个随机数
            buffer.add(value); // 将随机数加入缓冲区
            System.out.println("Produced: " + value); // 打印生产的值
            csu.signalAll(); // 唤醒消费休息室里面的消费线程
        } finally {
            lock.unlock(); // 释放锁
        }
    }

    // 消费者方法
    public void consume() {
        lock.lock(); // 加锁
        try {
            while (buffer.isEmpty()) { // 缓冲区为空时
                try {
                    csu.await(); // 消费线程进入消费休息室
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            int value = buffer.removeFirst(); // 从缓冲区取出一个值
            System.out.println("Consumed: " + value); // 打印消费的值
            pro.signalAll(); //  唤醒生产休息室内的生产线程
        } finally {
            lock.unlock(); // 释放锁
        }
    }
}

// 主类
public class Main {
    public static void main(String[] args) {
        ProducerConsumer pc = new ProducerConsumer(); // 创建生产者消费者对象

        // 创建生产者线程
        Thread producerThread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                pc.produce(); // 调用生产者方法
            }
        });

        // 创建消费者线程
        Thread consumerThread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                pc.consume(); // 调用消费者方法
            }
        });

        // 启动生产者和消费者线程
        producerThread.start();
        consumerThread.start();
    }
}

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值