手写迷你版BlockingQueue阻塞队列

手写MiniBlockingQueue阻塞队列

BlockingQueue接口

package com.xiaozhou;

public interface BlockingQueue<T> {

    void put(T element) throws InterruptedException;

    T take() throws InterruptedException;
}

MiniBlockingQueue

package com.xiaozhou;

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

public class MiniBlockingQueue<T> implements BlockingQueue<T>{

    //底层是一个数组
    private Object[] elementData;
    private int size;

    public MiniBlockingQueue(int size) {
        this.elementData = new Object[size];
        this.size = size;
    }

    //当前队列中的元素个数, put时的指针索引, take时的指针索引
    private int count , putIndex, takeIndex;

    private Lock lock = new ReentrantLock();

    private Condition fullCondition = lock.newCondition();

    private Condition emptyCondition = lock.newCondition();


    @Override
    public void put(T element) throws InterruptedException {

        lock.lock();

        try {
            //当阻塞队列满时 该put的线程需要进入条件队列中等待
            if (count == size){
                fullCondition.await();
            }

            elementData[putIndex] = element;

            putIndex++;

            count++;

            if (putIndex == size) putIndex = 0;

            //通知take阻塞的线程来消费
            emptyCondition.signal();
        } finally {
            lock.unlock();
        }


    }

    @Override
    public T take() throws InterruptedException {

        lock.lock();
        try {
            //当队列为空时,需要进入条件队列中等待
            if (count == 0){
                emptyCondition.await();
            }

            Object element = elementData[takeIndex];

            takeIndex++;
            count--;

            if (takeIndex == size) takeIndex = 0;

            fullCondition.signal();

            return (T) element;
        } finally {
            lock.unlock();
        }
    }

    //测试
    public static void main(String[] args) throws InterruptedException {

        MiniBlockingQueue<String> queue = new MiniBlockingQueue<String>(3);


        // 当阻塞队列中为空时take 会阻塞,直到有生产者放进去值才会take到
//        new Thread(()->{
//            try {
//                String element = queue.take();
//                System.out.println(Thread.currentThread().getName() + " 从队列中获取值为: " + element);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        },"A").start();
//
//
//        TimeUnit.SECONDS.sleep(2);
//
//        queue.put("zzp");


        // 当阻塞队列中值满时,再去put则会阻塞,直到有消费者消费后才会put进去
        new Thread(()->{
            for (int i = 0; i < 4; i++) {
                try {
                    queue.put(String.valueOf(i));
                    System.out.println(Thread.currentThread().getName() + "放入:" + String.valueOf(i));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();


        TimeUnit.SECONDS.sleep(2);


        for (int i = 0; i < 4; i++) {
            String res = queue.take();
            System.out.println(Thread.currentThread().getName() + "获取到:" + res);
        }
    }
}

posted @   s686编程传  阅读(130)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2019-07-30 面向对象之反射,元类
点击右上角即可分享
微信分享提示