基于LinkedBlockingQueue源码自我实现线程安全队列

LinkedBlockingQueue是一个阻塞的、线程安全的、由链表实现的双向队列,和ArrayBlockingQueue一样,是最普通也是最常用的阻塞队列。现基于LinkedBlockingQueue源码自我实现一个单向的、简化版的LinkedBlockingQueue.

package com.lzq.newInterview;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class MyLinkedBlockingQueue<E> {

    private Node<E> head;// 队头
    private Node<E> tail;// 队尾

    private static final int DEFALT_SIZE = 20;
    private int size;// 队列最大长度

    private int count;// 队列当前容量

    private ReentrantLock lock = new ReentrantLock();
    private Condition empty = lock.newCondition();
    private Condition full = lock.newCondition();

    public MyLinkedBlockingQueue() {
        head = null;
        tail = null;
        size = DEFALT_SIZE;
    }

    public MyLinkedBlockingQueue(int size) {
        head = null;
        tail = null;
        this.size = size;
    }

    // 队列尾部插入元素
    public void offer(E e) {
        if (e == null)
            return;
        try {
            lock.lock();
            while (count == size) {
                full.await();
            }
            if (head == null && tail == null) {
                Node<E> node = new Node<E>(e, null);
                head = node;
                tail = node;
            } else {
                Node<E> node = new Node<E>(e, null);
                tail.next = node;
                tail = node;
            }
            count++;
            System.out.println("offer: count=" + this.count);
            empty.signal();
        } catch (Exception exp) {
            exp.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public E poll() {
        try {
            lock.lock();
            while (count == 0) {
                empty.await();
            }
            E oldValue = head.value;
            head = head.next;
            if (head == null)
                tail = null;
            count--;
            System.out.println("poll: count=" + this.count);
            full.signal();
            return oldValue;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return null;
    }

    static class Node<E> {
        Node<E> next;
        E value;

        Node(E value, Node<E> next) {
            this.value = value;
            this.next = next;
        }
    }

    public static void main(String[] args) {
        final MyLinkedBlockingQueue<Integer> queue = new MyLinkedBlockingQueue<Integer>();
        for (int i = 0; i < 100; i++) {
            final int num = i;
            Thread t = new Thread(new Runnable() {
                public void run() {
                    queue.offer(num);
                }
            });
            t.start();
        }
        for (int i = 0; i < 100; i++) {
            Thread t = new Thread(new Runnable() {
                public void run() {
                    queue.poll();
                }
            });
            t.start();
        }
    }
}

部分运行结果:

offer: count=1
offer: count=2
offer: count=3
offer: count=4
offer: count=5
offer: count=6
offer: count=7
offer: count=8
offer: count=9
offer: count=10
offer: count=11
offer: count=12
poll: count=11
poll: count=10
poll: count=9
poll: count=8
poll: count=7
poll: count=6
poll: count=5
poll: count=4
poll: count=3
poll: count=2
poll: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
offer: count=2
offer: count=3
poll: count=2
poll: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
offer: count=2
poll: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
offer: count=2
poll: count=1
poll: count=0
offer: count=1
offer: count=2
poll: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
offer: count=2
poll: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
poll: count=0
offer: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
offer: count=2
poll: count=1
poll: count=0

时间: 2024-10-26 03:50:23

基于LinkedBlockingQueue源码自我实现线程安全队列的相关文章

jQuery源码分析系列(38) : 队列操作

Queue队列,如同data数据缓存与Deferred异步模型一样,都是jQuery库的内部实现的基础设施 Queue队列是animate动画依赖的基础设施,整个jQuery中队列仅供给动画使用 Queue队列 队列是一种特殊的线性表,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).队列的特点是先进先出(FIFO-first in first out),即最先插入的元素最先被删除. 为什么要引入队列? 我们知道代码的执行流有异步与同步之分,例如 var a

LambdaMART简介——基于Ranklib源码(一 lambda计算)

学习Machine Learning,阅读文献,看各种数学公式的推导,其实是一件很枯燥的事情.有的时候即使理解了数学推导过程,也仍然会一知半解,离自己写程序实现,似乎还有一道鸿沟.所幸的是,现在很多主流的Machine Learning方法,网上都有open source的实现,进一步的阅读这些源码,多做一些实验,有助于深入的理解方法. Ranklib就是一套优秀的Learning to Rank领域的开源实现,其主页在:http://people.cs.umass.edu/~vdang/ran

基于 cm-11 源码编译模拟器

以前对于cm的源码编译都是基于固定机型的,有的时候需要使用模拟器,这边就记录一下使用cm的源码来如何编译android 模拟器,不过在做这件事情前你最好评估一下自己的机器配置.这里给出的推荐的配置是,i5以上的cpu,硬盘要固态硬盘,否则模拟器的启动和加载的速度几乎不可以忍受. android源码编译完成以后生成的目录都是在源码目录下的out文件夹下 out/target 表示生成的是目标机器一般是手机上的各种程序,比如rom等 out/host   表示生成的是对于宿主机器上的各种工具,比如a

LinkedBlockingQueue源码分析

1. LinkedBlockingQueue源码分析(JDK8) 2. LinkedBlockingQueue源码分析 啦啦啦

理解ThreadPoolExecutor源码(一)线程池的corePoolSize、maximumPoolSize和poolSize

我们知道,受限于硬件.内存和性能,我们不可能无限制的创建任意数量的线程,因为每一台机器允许的最大线程是一个有界值.也就是说ThreadPoolExecutor管理的线程数量是有界的.线程池就是用这些有限个数的线程,去执行提交的任务.然而对于多用户.高并发的应用来说,提交的任务数量非常巨大,一定会比允许的最大线程数多很多.为了解决这个问题,必须要引入排队机制,或者是在内存中,或者是在硬盘等容量很大的存储介质中.J.U.C提供的ThreadPoolExecutor只支持任务在内存中排队,通过Bloc

java并发编程基础-ReentrantLock及LinkedBlockingQueue源码分析

ReentrantLock是一个较为常用的锁对象.在上次分析的uil开源项目中也多次被用到,下面谈谈其概念和基本使用. 概念 一个可重入的互斥锁定 Lock,它具有与使用 synchronized 相同的一些基本行为和语义,但功能更强大. 名词解释: 互斥 表示同一时刻,多个线程中,只能有一个线程能获得该锁.但是多个线程都可以调用lock方法,只有一个会成功,其他的线程会被阻塞,直到该锁被释放 可重入 模仿synchronized 的语义:如果线程进入由线程已经拥有的监控器保护的 synchro

[一起读源码]走进C#并发队列ConcurrentQueue的内部世界

决定从这篇文章开始,开一个读源码系列,不限制平台语言或工具,任何自己感兴趣的都会写.前几天碰到一个小问题又读了一遍ConcurrentQueue的源码,那就拿C#中比较常用的并发队列ConcurrentQueue作为开篇来聊一聊它的实现原理. 话不多说,直奔主题. 要提前说明下的是,本文解析的源码是基于.NET Framework 4.8版本,地址是:https://referencesource.microsoft.com/#mscorlib/system/Collections/Concur

nginx源码分析——线程池

源码: nginx 1.13.0-release 一.前言 nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影响.但是经常会有人问道,nginx为什么不采用多线程模型(这个除了之前一篇文章讲到的情况,别的只有去问作者了,HAHA).其实,nginx代码中提供了一个thread_pool(线程池)的核心模块来处理多任务的.下面就本人对该thread_pool这个模块的理解来跟大家做些分享(文中错误.不足还请大家指出,谢谢)

jQuery 源码解析(八) 异步队列模块 Callbacks 回调函数详解

异步队列用于实现异步任务和回调函数的解耦,为ajax模块.队列模块.ready事件提供基础功能,包含三个部分:Query.Callbacks(flags).jQuery.Deferred(funct)和jQuery.when().本节讲解Callbacks,也就是回调函数列表 回调函数用于管理一组回调函数,支持添加.移除.触发.锁定和禁用回调函数,为jQuery.ajax.jQuery.Deferred()和ready()事件提供基础功能,我们也可以基于它编写新的组件. 使用方法:$.Callb