手写链表阻塞队列的添加和获取功能 ✨ 每日积累

简介: 手写链表阻塞队列的添加和获取功能 ✨ 每日积累
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class LinkedBlockingQueueTest<E> {
    //添加数据时的锁
    private final ReentrantLock putLock = new ReentrantLock();
    //获取数据时的锁
    private final ReentrantLock getLock = new ReentrantLock();
    //容器容量
    private final int capacity;
    //当前元素总数量
    private final AtomicInteger currentElementCount = new AtomicInteger();
    //一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
    //尾巴节点
    private transient Node<E> last;
    //头节点
    transient Node<E> head;
    /**
     * Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,
     * 相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。
     */
    //等待拿数据的等待队列
    private Condition notNull = getLock.newCondition();
    //等待添加数据的等待队列
    private Condition notFull = putLock.newCondition();
    public void put(E element) throws InterruptedException{
        if (element == null) throw new InterruptedException();
        int count = -1;
        Node<E> currentNeedAddNode = new Node<>(element);
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger currentElementCount = this.currentElementCount;
        //上锁
        putLock.lockInterruptibly();
        try{
            //当前元素数量等于容量大小时线程等待
            while (currentElementCount.get() == capacity){
                notFull.await();
            }
            enqueue(currentNeedAddNode);
            count = currentElementCount.incrementAndGet();
            if (count + 1 < capacity) //唤醒
                notFull.signal();
        }finally {
            //锁释放
            putLock.unlock();
        }
        if (count == 0) signalNotEmpty();
    }
    public E get() throws InterruptedException {
        E getElement;
        int count = -1;
        final ReentrantLock getLock = this.getLock;
        final AtomicInteger currentElementCount = this.currentElementCount;
        //上锁
        getLock.lockInterruptibly();
        try {
            while (currentElementCount.get() == 0){
                //等待
                notNull.await();
            }
            getElement = dequeue();
            count = currentElementCount.getAndDecrement();
            if (count > 1) //唤醒
                notNull.signal();
        }finally {
            getLock.unlock();
        }
        if (count == capacity)
            signalNotFull();
        return getElement;
    }
    //当获取数据时发出等待信号,一般不会阻塞添加数据
    private void signalNotEmpty() {
        final ReentrantLock getLock = this.getLock;
        getLock.lock();
        try {
            notNull.signal();
        }finally {
            getLock.unlock();
        }
    }
    //添加数据时的等待信号,一般不会阻塞获取数据
    private void signalNotFull() {
        final ReentrantLock putLock = this.putLock;
        putLock.lock();
        try {
            notFull.signal();
        } finally {
            putLock.unlock();
        }
    }
    //从尾节点插入
    private void enqueue(Node<E> element){
        last.next = element;
        last = last.next;
    }
    //获取头节点元素并移除
    private E dequeue() {
        Node<E> h = head;
        Node<E> first = h.next;
        h.next = h;
        head = first;
        E x = first.item;
        first.item = null;
        return x;
    }
    public LinkedBlockingQueueTest() {
        this(Integer.MAX_VALUE);
    }
    public LinkedBlockingQueueTest(int size) {
        if (size <= 0) throw new IllegalArgumentException();
        this.capacity = size;
        //给头节点尾节点初始化
        head = new Node<>(null);
        last = head;
    }
    /**
     * 链表节点类
     * @param <E>
     */
    static class Node<E> {
        E item;
        //真正的后续节点,如果head.next = null,表示没有后续节点(这是最后一个节点)
        Node<E> next;
        Node(E x) {
            item = x;
        }
    }
}
相关文章
|
2月前
|
存储 测试技术 C语言
C语言实现链表的各种功能
本文详细介绍了如何使用C语言实现链表的各种功能,包括链表节点结构的定义与操作函数的实现。链表作为一种常用的数据结构,具有节点自由插入删除、动态变化等特点。文中通过`link_list.h`和`link_list.c`两个文件,实现了链表的初始化、插入、删除、查找、修改等核心功能,并在`main.c`中进行了功能测试。这些代码不仅展示了链表的基本操作,还提供了丰富的注释帮助理解,适合作为学习链表的入门资料。
单链表————单链表的构建,增删查改功能的实现
单链表————单链表的构建,增删查改功能的实现
【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能(2)
【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能(2)
67 0
|
存储
【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能
【数据结构】图文并茂,通过逻辑图带你轻松拿捏链表,实现各种接口功能
141 0
|
Java
Java实现单链表以及各种功能
单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。
148 0
Java实现单链表以及各种功能
|
算法 Python
python与算法:单链表剖分函数(对链表的元素可以按照是否满足特定功能切分为两个新的链表)
python与算法:单链表剖分函数(对链表的元素可以按照是否满足特定功能切分为两个新的链表)
90 0
创建单链表 打印单链表 插入删除节点 查找功能
创建单链表 打印单链表 插入删除节点 查找功能
86 0
|
安全
基于链表的有界阻塞队列 —— LinkedBlockingQueue
上一节看了基于数据的有界阻塞队列 ArrayBlockingQueue 的源码,通过阅读源码了解到在 ArrayBlockingQueue 中入队列和出队列操作都是用了 ReentrantLock 来保证线程安全。下面咱们看另一种有界阻塞队列:LinkedBlockingQueue。
179 0
|
算法 安全 Java
【Java数据结构及算法实战】系列010:Java队列04——链表实现的阻塞队列LinkedBlockingQueue
【Java数据结构及算法实战】系列010:Java队列04——链表实现的阻塞队列LinkedBlockingQueue
140 0
|
存储 算法 Java
Java实现单向链表基本功能
一、前言 最近在回顾数据结构与算法,有部分的算法题用到了栈的思想,说起栈又不得不说链表了。数组和链表都是线性存储结构的基础,栈和队列都是线性存储结构的应用~ 本文主要讲解单链表的基础知识点,做一个简单的入门~如果有错的地方请指正 二、回顾与知新 说起链表,我们先提一下数组吧,跟数组比较一下就很理解链表这种存储结构了。
1274 0