1,队列
@Slf4j
@Component
public class RedisMessageQueue {
@Autowired
private Jedis jedis;
private String key = "redis-queue";
public RedisMessageQueue() {
}
private static final String SCRIPT = "local table = redis.call('ZRANGEBYSCORE', KEYS[1], ARGV[1], ARGV[2]);\n" +
"\n" +
"local key = table[1];\n" +
"\n" +
"if key == nil then\n" +
"\treturn nil;\n" +
"else\n" +
"\tredis.call('ZREM', KEYS[1], key);\n" +
"\treturn key;\n" +
"end";
public void put(String message, long delayTime, TimeUnit unit) {
long timeout = TimeUnit.MILLISECONDS.convert(delayTime, unit);
jedis.zadd(key, Instant.now().toEpochMilli() + timeout, message);
}
public String poll() {
List<String> argvs = Lists.newArrayList();
argvs.add("0");
argvs.add(String.valueOf(Instant.now().toEpochMilli()));
Object result = jedis.eval(SCRIPT, Collections.singletonList(key), argvs);
if (Objects.isNull(result)) {
return null;
}
return String.valueOf(result);
}
}
lua脚本
local table = redis.call('ZRANGEBYSCORE', KEYS[1], ARGV[1], ARGV[2]);
local key = table[1];
if key == nil then
return nil;
else
redis.call('ZREM', KEYS[1], key);
return key;
end
2,消费者线程
@Slf4j
public class LoggerWorker implements Runnable {
private RedisMessageQueue redisMessageQueue;
public LoggerWorker(RedisMessageQueue redisMessageQueue) {
this.redisMessageQueue = redisMessageQueue;
}
@Override
public void run() {
while (! Thread.interrupted()) {
String message;
if ((message = redisMessageQueue.poll()) != null) {
log.info("{} 执行 {}", Thread.currentThread().getName(), message);
} else {
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
log.error("", e);
break;
}
}
}
}
}
3,调用示例
生产:
@PostMapping("/producer")
public void push(String message, long delay) {
redisMessageQueue.put(message, delay, TimeUnit.MILLISECONDS);
}
消费:
@PostMapping("/consumer")
public void newThread() {
Thread consumer = new Thread(new LoggerWorker(redisMessageQueue));
consumer.setDaemon(true);
consumer.start();
}
转载于:https://blog.51cto.com/tianyiya/2307642