是否有同样的经历?面试官问你做过啥项目,我一顿胡侃,项目利用到了消息队列,kafka,rocketMQ等等。

好的,那请开始你的表演,面试官递过一支笔:给我手写一个消息队列!!WHAT?

为了大家遇到这种场景还能愉快的zhuangbi,所以写一篇文章,凑合用一下。

想要实现一个消息队列,我们需要关组以下几点:

1.首先有一个队列(FIFO)来存放消息

2.消息队列容量有限

3.需要入队,出队方法

4.需要考虑多线程并发情况

<1>.简单版:用LinkedList实现一个简单的消息队列

这里用LinkedList来实现队列,然后通过synchronized关键字来实现多线程的互斥,用LinkedList的addLast方法实现队列的push,用LinkedList的removeFirst实现队列的remove方法

//实现FIFO队列
public class MyList<T> {
private LinkedList<T> storage = new LinkedList<T>();
private int statckSize = 2000;
public synchronized void push(T e) {//需要加上同步
storage.addLast(e);
} public synchronized T peek() {
if(storage!=null&&storage.size()>0){
return storage.peekFirst();
}
return null; } public void remove() {
storage.removeFirst();
} public boolean empty() {
return storage.isEmpty();
}
}

测试类:

public class ListTest {
public static void main(String[] args) {
MyList<String> myList = new MyList<String>();
for(String s : "the prefect code".split(" ")){//LIFO
myList.push(s);
}
while(!myList.empty()){
System.out.print(myList.peek()+" ");
myList.remove();
}
} }

<2>.进阶版,仍然用LinkedList来实现队列,给出仓库的概念(消息队列仓库),生产者和消费者分别在独立线程中实现,使用object的wait(),notify()和synchronized()实现线程操作的同步与互斥(Obj.wait(),与Obj.notify()必须要与synchronized(Obj)一起使用,也就是wait,与notify是针对已经获取了Obj锁进行操作,从语法角度来说就是Obj.wait(),Obj.notify必须在synchronized(Obj){...}语句块内。)

抽象仓库类:

public interface AbstractStorage {
void consumer(int num);
void producer(int num);
}

生产者线程:

class Producer extends Thread {
//生产数量
private int num;
//仓库
private AbstractStorage abstractStorage; public Producer(AbstractStorage abstractStorage,int num){
this.abstractStorage=abstractStorage;
this.num=num;
}
// 调用仓库Storage的生产函数
public void produce(int num){
abstractStorage.producer(num);
}
// 线程run函数
@Override
public void run(){
produce(num);
} }

消费者线程:

class Consumer extends Thread {
//消费数量
private int num;
//仓库
private AbstractStorage abstractStorage; public Consumer(AbstractStorage abstractStorage,int num){
this.abstractStorage=abstractStorage;
this.num=num;
} public void consume(int num){
abstractStorage.consumer(num);
} @Override
public void run(){
consume(num);
} }

消息队列(仓库)实现类:

public class Storage1 implements AbstractStorage {
//最大容量
private final int MAX_SIZE = 100;
//存储载体
private LinkedList list =new LinkedList(); @Override
public void consumer(int num) {
synchronized (list) {
while (num > list.size()) {
try {
list.wait();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("【阻塞】当前要消费的数量:" + num + ",当前库存量:" + list.size() + "当前消费阻塞");
}
for (int i = 0; i < num; i++) {
list.removeFirst();
}
System.out.println("【consumer】 "+Thread.currentThread().getName()+" 已消费产品数:" + num + ",现库存数:" + list.size());
list.notifyAll();
}
} //生产
@Override
public void producer(int num) {
synchronized (list) {
while (list.size() + num > MAX_SIZE) {
try {
list.wait();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("【阻塞】当前队列已满,生产阻塞");
}
for (int i = 0; i < num; i++) {
list.addLast(new Object());
}
System.out.println("【producer】 "+Thread.currentThread().getName()+ " 已生产产品数:" + num + ",现库存数:" + list.size());
list.notifyAll();
}
} }

测试类:

public class Test {
public static void main(String[] args) {
AbstractStorage abstractStorage =new Storage1(); //生产者对象
Producer p1 = new Producer(abstractStorage,10);
Producer p2 = new Producer(abstractStorage,10);
Producer p3 = new Producer(abstractStorage,10);
Producer p4 = new Producer(abstractStorage,10);
Producer p5 = new Producer(abstractStorage,10);
Producer p6 = new Producer(abstractStorage,10);
Producer p7 = new Producer(abstractStorage,10);
Producer p8 = new Producer(abstractStorage,50);
//消费者对象
Consumer c1 = new Consumer(abstractStorage,20);
Consumer c2 = new Consumer(abstractStorage,30);
Consumer c3 = new Consumer(abstractStorage,50); c1.start();
c2.start();
c3.start(); p1.start();
p2.start();
p3.start();
p4.start();
p5.start();
p6.start();
p7.start();
p8.start(); } }

最终结果显示,我们能实现简单的生产消费,并且是线程同步的。

用过消息队列?Kafka?能否手写一个消息队列?懵的更多相关文章

  1. 教你如何使用Java手写一个基于链表的队列

    在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...

  2. 只会用就out了,手写一个符合规范的Promise

    Promise是什么 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果.从语法上说,Promise 是一个对象,从它可以获取异步操作的消息.Prom ...

  3. 利用SpringBoot+Logback手写一个简单的链路追踪

    目录 一.实现原理 二.代码实战 三.测试 最近线上排查问题时候,发现请求太多导致日志错综复杂,没办法把用户在一次或多次请求的日志关联在一起,所以就利用SpringBoot+Logback手写了一个简 ...

  4. 手写一个LRU工具类

    LRU概述 LRU算法,即最近最少使用算法.其使用场景非常广泛,像我们日常用的手机的后台应用展示,软件的复制粘贴板等. 本文将基于算法思想手写一个具有LRU算法功能的Java工具类. 结构设计 在插入 ...

  5. 【redis前传】自己手写一个LRU策略 | redis淘汰策略

    title: 自己手写一个LRU策略 date: 2021-06-18 12:00:30 tags: - [redis] - [lru] categories: - [redis] permalink ...

  6. 手写一个线程池,带你学习ThreadPoolExecutor线程池实现原理

    摘要:从手写线程池开始,逐步的分析这些代码在Java的线程池中是如何实现的. 本文分享自华为云社区<手写线程池,对照学习ThreadPoolExecutor线程池实现原理!>,作者:小傅哥 ...

  7. 『练手』手写一个独立Json算法 JsonHelper

    背景: > 一直使用 Newtonsoft.Json.dll 也算挺稳定的. > 但这个框架也挺闹心的: > 1.影响编译失败:https://www.cnblogs.com/zih ...

  8. 【spring】-- 手写一个最简单的IOC框架

    1.什么是springIOC IOC就是把每一个bean(实体类)与bean(实体了)之间的关系交给第三方容器进行管理. 如果我们手写一个最最简单的IOC,最终效果是怎样呢? xml配置: <b ...

  9. 放弃antd table,基于React手写一个虚拟滚动的表格

    缘起 标题有点夸张,并不是完全放弃antd-table,毕竟在react的生态圈里,对国人来说,比较好用的PC端组件库,也就antd了.即便经历了2018年圣诞彩蛋事件,antd的使用者也不仅不减,反 ...

随机推荐

  1. 108、如何使用 Secret? (Swarm15)

    参考https://www.cnblogs.com/CloudMan6/p/8068057.html   我们经常要想容器传递敏感信息,最常见的就是密码.比如:   docker run -e MYS ...

  2. IAP技术原理

    目录 IAP技术原理 更新记录 IAP与ISP的概念及原理 ISP简介 ISP原理 IAP简介 IAP原理 IAP优势 IAP的设计 1.程序启动流程 2.中断向量表的重定位 3.IAP跳转APP函数 ...

  3. 08 Python之内存管理

    python中的内存管理,从浅层次来说,可以分为3个方面来讲: 1,引用计数: python中引用计数,为了跟踪内存的对象 当创建对象的时候即被引用了,当对象不再被使用时,即某个对象的引用计数为0,它 ...

  4. Java读取利用java.util类Properties读取resource下的properties属性文件

    说明:upload.properties属性文件在resources下 import java.io.IOException;import java.io.InputStream;import jav ...

  5. git ignore 如何忽略已经提交的文件修改

    git ignore git ignore的作用很简单,本地仓库忽略一些文件的修改. ignore的规格可以按文件匹配,按后缀匹配或者按文件夹匹配. 如果在项目开发过程中,需要忽略某一个文件已经提交的 ...

  6. 从0开始Jmeter接口测试实战

    在之前的文章中给大家介绍过接口测试文档和接口测试用例示例,本文基于Jmeter工具给大家介绍一下如何实现接口测试用例:包括发起Http请求,绕过登陆,验证响应.JMeter是Apache组织开发的基于 ...

  7. Python中的序列

    Python中有四种内建的数据结构,即列表.元组.字典.集合.其中字典和集合我会以后再写,现在先说列表和元组,它们两个和以前提到很多次的字符串, 其实都属于——序列. 一.列表(list): 1. l ...

  8. poj1015 Jury Compromise[背包]

    每一件物品有两个属性.朴素思想是把这两种属性都设计到状态里,但空间爆炸.又因为这两个属性相互间存在制约关系(差的绝对值最小),不妨把答案设计入状态中,设$f[i][j]$选$i$个人,两者之差$j$. ...

  9. CH5102/SPOJ?? Mobile Service/P4046 [JSOI2010]快递服务[线性dp+卡常]

    http://contest-hunter.org:83/contest/0x50%E3%80%8C%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E3%80%8D%E4%B ...

  10. 【hiho1087】Hamiltonian Cycle

    题目大意:给定一个 N 个点的有向图,计数图上哈密顿回路的条数. 题解:哈密顿回路需要经过除了初始位置,每个点恰好一次.如果已知一条哈密顿回路的方向,那么从这条路上任意一个点出发,得到的都是同样的结果 ...