1.目录 

  • 延迟队列
  • 进一步优化

2.延迟队列

package com.redis;

import java.lang.reflect.Type;
import java.util.Set;
import java.util.UUID; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import redis.clients.jedis.Jedis; public class RedisDelayingQueue<T> {
static class TaskItem<T> {
public String id;
public T msg;
} // fastjson 序列化对象中存在 generic 类型时,需要使用 TypeReference
private Type TaskType = new TypeReference<TaskItem<T>>() {
}.getType();
private Jedis jedis;
private String queueKey; public RedisDelayingQueue(Jedis jedis, String queueKey) {
this.jedis = jedis;
this.queueKey = queueKey;
} public void delay(T msg) {
TaskItem<T> task = new TaskItem<T>();
task.id = UUID.randomUUID().toString(); // 分配唯一的 uuid
task.msg = msg;
String s = JSON.toJSONString(task); // fastjson 序列化
jedis.zadd(queueKey, System.currentTimeMillis() + , s); // 塞入延时队列 ,5s 后再试
} public void loop() {
while (!Thread.interrupted()) { // 只取一条
Set<String> values = jedis.zrangeByScore(queueKey, , System.currentTimeMillis());
if (values.isEmpty()) {
try {
Thread.sleep(); // 歇会继续
} catch (InterruptedException e) {
break;
}
continue;
}
String s = values.iterator().next();
if (jedis.zrem(queueKey, s) > ) { // 抢到了
TaskItem<T> task = JSON.parseObject(s, TaskType); // fastjson 反序列化
this.handleMsg(task.msg);
}
}
} public void handleMsg(T msg) {
System.out.println(msg);
} public static void main(String[] args) {
Jedis jedis = new Jedis();
RedisDelayingQueue<String> queue = new RedisDelayingQueue<>(jedis, "q-demo"); Thread producer = new Thread(() -> {
for (int i = ; i < ; i++) {
queue.delay("codehole" + i);
}
}); Thread consumer = new Thread(() -> queue.loop());
producer.start();
consumer.start();
try {
producer.join();
Thread.sleep();
consumer.interrupt();
consumer.join();
} catch (InterruptedException e) {
}
}
}

3.进一步优化

上面的算法中同一个任务可能会被多个进程取到之后再使用zrem进行争抢,那 些没抢到的进程都是白取了一次任务,这是浪费。可以考虑使用lua scripting来 优化一下这个逻辑,将zrangebyscore和zrem一同挪到服务器端进行原子化操 作,这样多个进程之间争抢任务时就不会出现这种浪费了

最新文章

  1. jQuery动画-圣诞节礼物
  2. Django:手把手带你入门
  3. Channel
  4. js类型检测
  5. 自动获取MyEcilipse注册名和注册码的方法
  6. LVS简单实现NAT&amp;DR模型
  7. URAL 1966 Cycling Roads 点在线段上、线段是否相交、并查集
  8. JSP内置对象的解析
  9. VC++ 学习笔记(三):摩登之路——C++/CLI简介
  10. 程序编码(机器级代码+汇编代码+C代码+反汇编)
  11. Scut:参数导入方式(有遗留疑问)
  12. SQL cmd 实用工具学习 -1
  13. STM32的LED驱动程序
  14. javscript eval()的优缺点与web安全防范
  15. HTTPS介绍
  16. Linux命令之rm
  17. C、C++、C#、Java、php、python语言的内在特性及区别
  18. 获取链接的参数,判断是否是微信打开,ajax获取数据
  19. css3实现画对号动画
  20. K近邻算法小结

热门文章

  1. ubuntu 为firefox 安装flash_player
  2. iOS开发之手势gesture详解(一)
  3. 腾讯IM的那些坑
  4. TreeSet, LinkedHashSet and HashSet 的区别
  5. 小W旅游railway
  6. mac安装.net core
  7. 2.【nuxt起步】-初始化创建nuxt项目
  8. python 工具 二进制文件处理之——大小端变换
  9. C#中toolStrip或statusStrip遮挡了SplitContainer怎么办?
  10. Flash如何为文字描边