java redis实现fifo,redis如何实现消息队列

一、复盘面试

遇到面试问到:如果我想在redis实现队列,会用到哪个命令?根据redis手册关于Redis 列表(List) 命令主要操作有四种非阻塞版lpush/lpop/rpush/rpop,两种阻塞版本blpop/brpop,l和r代表左(left)和右(right)缩写,push代表添加也叫压入,pop代表弹出。基本满足先进入先出(FIFO)效果就完成了基本的队列,本次GitHub实验代码仓库。

通过命令模拟队列

RDM Redis Console

连接中...

已连接。

localhost:0>lpush mylist a b c d

"4"

localhost:0>rpop mylist

"a"

localhost:0>rpop mylist

"b"

localhost:0>rpop mylist

"c"

localhost:0>rpop mylist

"d"

localhost:0>rpop mylist

null

localhost:0>

复制代码

二、java模拟队列实现生产者消费者模式

redis配置常量

package io.charles;

public class Constant {

/**

* redis链接地址

*/

public static final String host = "127.0.0.1";

/**

* redis启动端口

*/

public static final int port = 6379;

/**

* 正式队列列表名称

*/

public static final String task_queue = "task-queue";

/**

* 临时队列列表名称

*/

public static final String tmp_queue = "tmp-queue";

}

复制代码

TaskProducer模拟生产者

package io.charles;

/**

* 用于模拟生产者

*/

import java.util.Random;

import java.util.UUID;

import redis.clients.jedis.Jedis;

public class TaskProducer implements Runnable {

Jedis jedis = new Jedis(Constant.host, Constant.port);

public void run() {

Random random = new Random();

while (true) {

try {

Thread.sleep(random.nextInt(600) + 600);

// 模拟生成一个任务

UUID taskid = UUID.randomUUID();

//将任务插入任务队列:task-queue

jedis.lpush(Constant.task_queue, taskid.toString());

System.out.println("插入了一个新的任务: " + taskid);

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

复制代码

TaskConsumer模拟消费者

package io.charles;

import java.util.Random;

import redis.clients.jedis.Jedis;

/**

* 模拟消费者

*/

public class TaskConsumer implements Runnable {

Jedis jedis = new Jedis(Constant.host, Constant.port);

public void run() {

Random random = new Random();

while (true) {

//从任务队列"task-queue"中获取一个任务,并将该任务放入临时队列"tmp-queue"

String taskid = jedis.rpoplpush(Constant.task_queue, Constant.tmp_queue);

// 模拟一下:睡觉

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

//模拟成功和失败的偶然现象

if (random.nextInt(13) % 7 == 0) {// 模拟失败的情况,概率为2/13

//将本次处理失败的任务从临时队列"tmp-queue"中,弹回任务队列"task-queue"

jedis.rpoplpush(Constant.task_queue, Constant.tmp_queue);

System.out.println(taskid + "处理失败,被弹回任务队列");

} else {// 模拟成功的情况

// 将本次任务从临时队列"tmp-queue"中清除

jedis.rpop(Constant.tmp_queue);

System.out.println(taskid + "处理成功,被清除");

}

}

}

}

复制代码

TaskShedulerSystem启动生产者和消费者线程

package io.charles;

public class TaskShedulerSystem {

public static void main(String[] args) throws Exception {

// 启动一个生产者线程,模拟任务的产生

new Thread(new TaskProducer()).start();

Thread.sleep(15000);

//启动一个线程者线程,模拟任务的处理

new Thread(new TaskConsumer()).start();

}

}

复制代码

三、参考资料

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值