模拟实现一个阻塞队列

模拟实现一个阻塞队列

背景:

最近在跟白老师学习,布置了一个作业,就是要自己写一个阻塞队列出来。

功能点:

开发出一个阻塞队列类,提供put()、take()方法。其中put()方法表示往队列里插入一个元素,如果队列容量不足,则等待,直到有空间为止。take()方法表示从队列里取出第一个元素,如果队列里没有元素,则等待,直到有元素为止。

知识点:

synchronized、wait()、notify()的使用

代码:

首先,是最核心的队列类:

package top.usjava.learn.springbootlearn.util;

import java.util.ArrayList;
import java.util.List;

/**
 * 第一周作业:模拟实现一个阻塞队列
 *
 * @author Owen
 * @date 2018/9/2 15:20
 */
public class MyBlockingQueue<T> {
    /**
     * 队列中的容器,用来放队列的元素
     */
    private final List<T> list = new ArrayList<>();
    /**
     * 队列的最大容量值
     */
    private final int maxSize;
    /**
     * 队列当前的元素个数
     */
    private int size = 0;
    /**
     * 锁
     */
    private final Object object = new Object();

    public MyBlockingQueue(int maxSize) {
        this.maxSize = maxSize;
    }

    /**
     * 插入一个元素到队列里,如果空间不足,则等待,直到有空间位置
     *
     * @param t the element to add
     * @throws InterruptedException if interrupted while waiting
     */
    public void put(T t) throws InterruptedException {
        synchronized (object) {
            while (size == maxSize) {
                object.wait();
            }
            list.add(t);
            size++;
            object.notify();
            System.out.println("queue size:"+size+" "+System.currentTimeMillis());
        }
    }

    /**
     * 移除队列中第一个元素,如果当前队列没有元素,则一直等待,直到有元素位置。
     *
     * @return the head of this queue
     * @throws InterruptedException if interrupted while waiting
     */
    public T take() throws InterruptedException{
        T t;
        synchronized (object) {
            while (size == 0) {
                object.wait();
            }
            t = list.remove(0);
            size--;
            System.out.println("queue size:"+size+" "+System.currentTimeMillis());
            //这里故意休眠500ms用于观察一定要take后才能继续put
            Thread.sleep(500L);
            object.notify();
        }
        return t;
    }

}

其次,建一个Bean类,用来稍后测试用:

package top.usjava.learn.springbootlearn.vo;

/**
 * 猪类
 *
 *
 * @author Owen
 * @date 2018/9/2 17:00
 */
public class Pig {
    /**
     * 名称
     * */
    String name;
    /**
     * 生日
     * */
    long bornTime;

    public Pig(String name, long bornTime) {
        this.name = name;
        this.bornTime = bornTime;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public long getBornTime() {
        return bornTime;
    }

    public void setBornTime(long bornTime) {
        this.bornTime = bornTime;
    }
}

测试类:

package top.usjava.learn.springbootlearn.testmain;

import top.usjava.learn.springbootlearn.util.MyBlockingQueue;
import top.usjava.learn.springbootlearn.vo.Pig;

/**
 * @Description: 测试MyBlockingQueue
 * @author Owen
 * @date 2018/9/2 16:36
 */
public class TestMyBlockingQueue {
    public static void main(String[] args) throws InterruptedException {
        //先初始化队列,并放入5个元素,这时,队列装满了
        MyBlockingQueue<Pig> employeeMyBlockingQueue = new MyBlockingQueue<>(5);
        employeeMyBlockingQueue.put(new Pig("A",System.currentTimeMillis()));
        employeeMyBlockingQueue.put(new Pig("B",System.currentTimeMillis()));
        employeeMyBlockingQueue.put(new Pig("C",System.currentTimeMillis()));
        employeeMyBlockingQueue.put(new Pig("D",System.currentTimeMillis()));
        employeeMyBlockingQueue.put(new Pig("E",System.currentTimeMillis()));
        //新的存放操作一开始会阻塞,直到下面第二个线程提取一个元素后,才有空间,才能存放成功
        Thread t1 = new Thread(()->{
            try {
                employeeMyBlockingQueue.put(new Pig("F",System.currentTimeMillis()));
                System.out.println("存放F成功");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.start();

        //提取一个元素出来
        Thread t2 = new Thread(()->{
            try {
                Thread.sleep(2000L);
                Pig pig = employeeMyBlockingQueue.take();
                System.out.println("取出了元素:"+pig.getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t2.start();
    }
}

运行结果:

这里写图片描述

从结果可以看出:

  1. 首先,程序往队列存放了5个元素
  2. 直到两秒后,先释放了一个A元素
  3. 又过了500ms后,F元素才插入成功
  4. “取出了元素:A”之所以在最后才出现是系统优先执行t1线程的输出了。其实从前三点已经知道队列是先取出A再放入F的。

    因此,模拟成功。有不正之处请多多指点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值