手写一个属于自己的阻塞队列

本文展示了如何利用Java的Condition和Lock构建一个阻塞队列,队列满时阻止插入,队列空时阻止取出。主要方法包括阻塞插入put和阻塞移除take,通过ReentrantLock和Condition实现线程间的同步与通信。在示例中,生产者线程不断向队列添加元素,消费者线程则从队列中取出并消费元素。
摘要由CSDN通过智能技术生成

咱们使用Condition和Lock实现一个自己的阻塞队列,容器使用List集合,Condition的await/signal、synchronized的await/notify/notifyall、LockSupport的park/unpark都是实现线程之间通信的,只是应用场景不一样。

什么是阻塞队列

队列是一种只允许在一端进行删除操作,在另一端进行插入操作的线性表,允许插入的一端称为队尾、允许删除的一端称为队头。

编码思路

主要有两个方法:

put:支持阻塞插入,队列满了的情况下,会阻塞继续往队列中添加数据的线程,直到队列元素被释放

take:支持阻塞移除,队列为空的情况下,会阻塞从队列中获取元素的线程,直到队列添加了新的元素

package com;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionBlockedQueueTest {
    //表示堵塞队列中的容器
    private List<String> items;
    //集合中已添加元素个数
    private volatile int size;
    //集合的容量
    private volatile int count;
    private Lock lock = new ReentrantLock();
    //让take取值方法堵塞
    private final Condition notEmpty = lock.newCondition();
    //让put添加方法堵塞
    private final Condition notFull = lock.newCondition();

    public ConditionBlockedQueueTest(int count) {
        this.count = count;
        items = new ArrayList<>(count);
    }

    /**
     * 阻塞方式添加元素
     */
    public void put(String e) throws InterruptedException {
        lock.lock();
        try {
            if(items.size() >= count){
                System.out.println("堵塞队列满了,需要等待");
                notFull.await();
            }
            ++size;//添加元素个数
            items.add(e);
            notEmpty.signal();
        }finally {
            lock.unlock();
        }
    }

    /**
     * 阻塞方法移除元素
     * @return
     * @throws InterruptedException
     */
    public String take() throws InterruptedException {
        lock.lock();
        try {
            if(items.isEmpty()){
                System.out.println("堵塞队列空了,需要等待添加元素");
                notEmpty.await();
            }
            --size;//减少元素个数
            String item = items.remove(0);
            notFull.signal();
            return item;
        }finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws Exception{
        ConditionBlockedQueueTest conditionBlockedQueueTest = new ConditionBlockedQueueTest(10);
        //生产者线程
        Thread t1 = new Thread(()->{
            for (int i=0; i< 100;i++) {
                try {
                    String val = "item-"+i;
                    conditionBlockedQueueTest.put(val);
                    System.out.println("生产一个元素:"+val);
                    Thread.sleep(new Random().nextInt(1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t1.start();
        Thread.sleep(1000);
        //消费者线程
        Thread t2 = new Thread(()->{
            for (;;) {
                try {
                    String result = conditionBlockedQueueTest.take();
                    System.out.println("消费者线程消费元素:"+result);
                    Thread.sleep(new Random().nextInt(100));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t2.start();
    }
}

结果

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泡^泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值