生产者&消费者模型

本文介绍了如何在Java中实现阻塞队列,包括基于标准库的`LinkedBlockingDeque`和自定义的阻塞队列实现。还讨论了如何添加线程安全和阻塞效果,利用wait和notify方法。此外,提到了消息队列Kafka在实际开发中的应用,作为消息传递的主流解决方案。
摘要由CSDN通过智能技术生成

优点:

1.能让多个服务器之间更充分的结合

2.能对于请求

实际开发中用到的”阻塞队列“不是一个简单的数据结构,而是一个专门的服务器程序,起个名字叫“消息队列”。kafka就是业界一个比较主流的消息队列。

基于内置的阻塞队列,实现一个简单的生产者消费者模型:

//基于标准库链表和数组实现的阻塞队列
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

public class Demo2 {
    public static void main(String[] args) throws InterruptedException {
        BlockingDeque<String> queue= new LinkedBlockingDeque<>();
        queue.put("hello");
        String s=queue.take();
    }
}

实现一个自己的阻塞队列:

1.先实现一个普通的队列(可以基于数组实现,也可以基于链表实现)

2.再加上线程安全

3.再加上阻塞

class MyBlockingQueue{
    //保存数据本体
    private int [] data=new int[100];
    //有效元素个数
    private int size=0;
    //队首下标
    private int head=0;
    //队尾下标
    private int tail=0;

    //入队列
    public void put(int value){
        //队列满了,返回
        if(size== data.length){
            return ;
        }
        data[tail]=value;
        tail++;
        //tail到达末尾的情况
        if(tail>= data.length){
            tail=0;
        }
        size++;
    }

    //出队列
    public Integer take(){
        //队列为空,返回非法值
        if(size==0){
            return null;
        }
        int ret=data[head];
        head++;
        //head到达末尾
        if(head>= data.length){
            head=0;
        }
        size--;
        return ret;
    }
}
public class Demo2 {
    public static void main(String[] args)  throws NullPointerException{
       //验证队列是否能正常工作
        MyBlockingQueue queue=new MyBlockingQueue();
        queue.put(1);
        queue.put(2);
        int ret=0;
        ret=queue.take();
        System.out.println(ret);
        ret=queue.take();
        System.out.println(ret);
    }
}

给整个方法加锁:

class MyBlockingQueue{
    //保存数据本体
    private int [] data=new int[100];
    //有效元素个数
    private int size=0;
    //队首下标
    private int head=0;
    //队尾下标
    private int tail=0;
    //专门的锁对象
    private Object locker=new Object();

    //入队列
    public void put(int value){
        synchronized (locker){
            //队列满了,返回
            if(size== data.length){
                return ;
            }
            data[tail]=value;
            tail++;
            //tail到达末尾的情况
            if(tail>= data.length){
                tail=0;
            }
            size++;
        }

    }

    //出队列
    public Integer take(){
        synchronized (locker){
            //队列为空,返回非法值
            if(size==0){
                return null;
            }
            int ret=data[head];
            head++;
            //head到达末尾
            if(head>= data.length){
                head=0;
            }
            size--;
            return ret;
        }
    }
}

实现阻塞效果:使用wait和notify

put的阻塞条件:队列满;take阻塞条件:队列空

针对哪个对象加锁,就让哪个对象wait。put中的wait要用take来唤醒

    public void put(int value) throws InterruptedException {
        synchronized (locker){
            //队列满了,返回
            if(size== data.length){
                //return ;
                //队列满了就加锁
(1)             locker.wait();
            }
            data[tail]=value;
            tail++;
            //tail到达末尾的情况
            if(tail>= data.length){
                tail=0;
            }
            size++;
            //如果入队列成功,则唤醒出队列take的等待
(2)         locker.notify();
        }

    }

    //出队列
    public Integer take() throws InterruptedException {
        synchronized (locker){
            //队列为空,返回非法值
            if(size==0){
                //return null;
(2)             locker.wait();
            }
            int ret=data[head];
            head++;
            //head到达末尾
            if(head>= data.length){
                head=0;
            }
            size--;
            //唤醒put
(1)         locker.notify();
            return ret;
        }
    }

有人等待,notify会唤醒;如果没有人等待,notify没有任何副作用。

notify只能唤醒随机的一个等待的线程,不能做到精准,要想精准唤醒,就要使用不同的锁对象

t1.wait对应t1.notify

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值