手写迷你版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);
}
}
}
万般皆下品,唯有读书高!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2019-07-30 面向对象之反射,元类