Java使用Redis实现类似消息队列的方法
前提条件:
SpringBoot项目集成了Redis,并且可以直接使用。本文使用SpringDataRedis的RedisTemplate实现。
实现效果:生产者能够向redis队列中不断发送数据。消费者可以不断的从该队列获取到该数据,进行处理。
核心代码:
redisTemplate.opsForList().leftPush(QUEUE, jsonObject);
JSONObject jsonObject = (JSONObject) redisTemplate.opsForList().rightPop(QUEUE, 10, TimeUnit.SECONDS);
AI解析:
使用Spring Data Redis的RedisTemplate类来操作Redis数据库中的列表数据结构。opsForList()方法提供了一系列操作列表的方法,例如leftPush和rightPop。
leftPush(String key, Object value)方法将给定的对象(这里是jsonObject)推入到列表的左侧(头部)。
rightPop(String key)方法从列表的右侧弹出元素并返回。这里还有一个可选的三个参数版本的方法rightPop(String key, long timeout, TimeUnit unit),这个方法会尝试从列表的右侧弹出一个元素,如果列表为空,则会等待直到有元素可用或者超时。
在你的代码中,你首先将jsonObject推入到名为READING_VISIT的列表的头部,然后尝试从该列表的尾部弹出元素,并且最多等待10秒来获取这个元素。如果在这10秒内没有元素可用,那么这个方法将返回null。
全部代码:
生产者:
try{
JSONObject jsonObject = new JSONObject();
jsonObject.put("data",data);
//发送队列
redisTemplate.opsForList().leftPush(QUEUE, jsonObject);
}catch (Exception e){
e.getMessage();
}
消费者:
1、新建一个配置类,实例化一个bean,在这个bean中单独启动线程:
@Configuration
public class QueueConfig {
@Autowired
private ConsumerServiceImpl consumerService;
@Bean
public String initConsume(){
//启动线程
consumerService.start();
return "success";
}
}
2、消费者从redis中不间断取值
@Slf4j
@Service
public class ConsumerServiceImpl extends Thread implements *** {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private bizService service;
private static final String QUEUE= "queue";
@Override
public void run() {
while (true) {
try {
// log.info("开始执行任务");
//阻塞式取值
JSONObject jsonObject = (JSONObject) redisTemplate.opsForList().rightPop(QUEUE, 10, TimeUnit.SECONDS);
//消息队列取到消息
if (jsonObject != null) {
System.out.println(jsonObject);
service.add(jsonObject);
log.info("Listening to a message, starting the task!");
}
} catch (Exception e) {
// 异常捕获,防止循环因异常停止
e.printStackTrace();
}
}
}
}
第二种方法:可以使用定时任务,持续从redis中取值处理,以下为AI实现:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class RedisListProcessor {
@Autowired
private StringRedisTemplate redisTemplate;
@Scheduled(fixedRate = 1000) // 每隔1秒执行一次
public void processRedisList() {
// 从Redis中取出列表的值进行处理
String value = redisTemplate.opsForList().rightPop("yourListKey");
if (value != null) {
// 进行处理逻辑
System.out.println("Processing value from Redis list: " + value);
}
}
}
定时任务的好处:
简单易用:Spring提供的定时任务功能可以方便地实现定时执行任务,不需要手动管理线程的创建和销毁。
可控性:定时任务可以通过注解的方式灵活控制执行频率、执行时间等,更加容易管理。
避免资源浪费:定时任务可以在处理完数据后自动释放资源,避免线程一直占用资源。
定时任务的缺点:
实时性不高:定时任务是按照预定的时间执行的,可能无法满足对数据实时性要求较高的场景。
灵活性较差:定时任务的执行时间是预先设定的,可能无法灵活应对数据变化。
使用新建线程的好处:
实时性高:通过新建线程不间断地读取Redis,可以更加实时地处理Redis中的数据。
灵活性高:可以根据需要动态调整线程的数量、执行逻辑等。
使用新建线程的缺点:
管理复杂:需要手动管理线程的创建、销毁、异常处理等,容易出现资源泄漏和线程安全问题。
可维护性差:使用新建线程会增加系统的复杂性,降低代码的可读性和可维护性。