基于redis实现消息队列
众所周知,redis是基于内存的数据库,速度非常快,不但可以用来存储缓存
还可以用作消息队列。
消息队列需要先进先出,redis中最符合的数据结构就是list了,所以我们采用
lpush命令往队列里生产消息,为了防止没有消息的时候循环空转,采用
brpop命令阻塞拉取消息
这里使用的是RedisTemplate
首先创建一个生产者类,收到请求就往队列里发送消息
@RestController
public class Producer {
@Autowired
private RedisTemplate redisTemplate;
@PostMapping("/sendMessage")
public void sendMessage() {
System.out.println("生产者生产");
String mg = String.valueOf(LocalDateTime.now());
redisTemplate.opsForList().leftPush("message", mg);
}
}
之后创建消费者类,消费者需要在容器启动时就开始监听队列里有无消息
所以需要继承CommandLineRunner接口
@Component
public class Consumer implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("消费者正在监听");
}
}
开启一个线程循环监听队列里的消息,再使用自定义线程池执行任务
private final static ThreadPoolExecutor executorService = new ThreadPoolExecutor(20, 30, 5,
TimeUnit.MINUTES, new ArrayBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy());
就当是复习线程使用了,再用一个继承了Runnable接口的内部类打印出接收到的消息
static class ConsumerRunner implements Runnable {
private String key;
private String mg;
public ConsumerRunner(String key, String mg) {
this.key = key;
this.mg = mg;
}
@Override
public void run() {
System.out.println("消费者消费" + key + ":" + mg);
}
}
消费者完整代码如下
@Component
public class Consumer implements CommandLineRunner {
@Autowired
RedisTemplate redisTemplate;
private final static ThreadPoolExecutor executorService = new ThreadPoolExecutor(20, 30, 5,
TimeUnit.MINUTES, new ArrayBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy());
@Override
public void run(String... args) {
System.out.println("消费者正在监听");
Thread residingThread = new Thread(() -> {
while (true) {
String mg;
do {
// 设置阻塞时间,防止循环空转
mg = (String) redisTemplate.opsForList().rightPop("message", 10000, TimeUnit.MILLISECONDS);
executorService.execute(new ConsumerRunner("message", mg));
} while (mg != null);
}
});
residingThread.start();
}
static class ConsumerRunner implements Runnable {
private String key;
private String mg;
public ConsumerRunner(String key, String mg) {
this.key = key;
this.mg = mg;
}
@Override
public void run() {
System.out.println("消费者消费" + key + ":" + mg);
}
}
}
启动之后执行监听方法
发送请求向队列添加消息,然后消费者打印出消息