Java实现阻塞队列

阻塞队列的实现原理
1、生产者向队尾添加元素
2、消费者向队头消费元素
3、添加和消费过程是线程安全的

实现一

public class MyBlockingContainer<T> {
    private Queue<T> queue=new LinkedList<>();
    private final int MAX;

    public MyBlockingContainer(int limit){
        this.MAX=limit;
    }

    public void put(T t) throws InterruptedException {
        synchronized (this){
            while(queue.size()==MAX){
                this.wait();//释放锁并且阻塞自己,要想唤醒必须先获取锁
            }
            queue.offer(t);
            this.notifyAll();//唤醒消费者线程,此时还没有释放锁
        }
    }

    public T get() throws InterruptedException {
        T t;
        synchronized (this){
            while(queue.size()==0){
                this.wait();
            }
            t=queue.poll();
            this.notifyAll();
        }
        return t;
    }
}

实现一的方法很简单,原理是synchronized+wait+notify实现,但是notify的时候是会唤醒生产者线程和消费者线程的,想象一下,当前生产者线程已经生产了MAX个元素,当他唤醒其他线程的时候,也会唤醒生产者线程,在这里显然是没有必要的。

实现二

public class MyBlockingQueueForLock<T> {
    private Queue<T> queue=new LinkedList<>();
    private final int MAX;
    private ReentrantLock lock=new ReentrantLock();
    private Condition producer=lock.newCondition();
    private Condition consumer=lock.newCondition();

    public MyBlockingQueueForLock(int limit){
        this.MAX=limit;
    }

    public void put(T t) throws InterruptedException {
        final ReentrantLock lock=this.lock;
        lock.lockInterruptibly();
        try {
            while(queue.size()==MAX){
                producer.await();//响应中断
            }
            queue.offer(t);
            consumer.signalAll();
        }finally {
            lock.unlock();
        }
    }

    public T get() throws InterruptedException {
        final ReentrantLock lock=this.lock;
        lock.lockInterruptibly();
        T t;
        try {
            while (queue.size()==0){
                consumer.await();//响应中断
            }
            t=queue.poll();
            producer.signalAll();
        }finally {
            lock.unlock();
        }
        return t;
    }
}

实现二用AQS的条件队列实现了唤醒线程的灵活性,可以说比实现一更进了一步

总结:JDK自带的阻塞队列其实原理和上面差不多,但是实现得更加灵活,支持高并发。比如LinkedBlockingQueue是用了两把不同的锁来实现,之所以可以这样,是因为链表结构

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java阻塞队列是一种线程安全的数据结构,它提供了同步的功能,用于在多线程环境中安全地进行数据交换和通信。其实现原理主要涉及以下几个方面。 首先,阻塞队列实现会使用锁机制确保线程安全。Java中可以使用ReentrantLock或synchronized关键字来实现锁,在对队列进行操作时会对其进行加锁,保证同一时刻只有一个线程能够访问队列。 其次,阻塞队列内部会使用条件变量或信号量来实现线程间的协调与通信。当队列为空时,消费者线程需要等待直到队列有数据可取;当队列已满时,生产者线程需要等待直到队列有空位置可放入新数据。通过条件变量或信号量的等待和唤醒机制,实现了线程间的同步和互斥。 此外,阻塞队列通常还会使用一个循环数组来存储数据。循环数组在插入和删除元素时能够高效地利用已分配的内存空间,避免了频繁的扩容和内存拷贝。同时,循环数组的读写指针可以通过取模运算得到,实现环形循环。 最后,阻塞队列还会根据不同的需求提供不同的阻塞操作。例如,用于插入元素的put()方法在队列已满时会阻塞直到有空位置可用,用于获取元素的take()方法在队列为空时会阻塞直到有数据可取。这些阻塞操作的实现依赖于同步和协调机制,保证了线程安全和数据一致性。 总之,Java阻塞队列通过使用锁、条件变量或信号量、循环数组等机制,实现了线程安全和线程间的同步与通信。它是多线程编程中常用的工具,能够有效地管理数据的生产和消费,提高多线程程序的可靠性和性能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值