什么是延时任务
- 简单来讲就是不知道开始时间是什么时候,开始时间是未知的没有固定的开始时间,用户的可以操作指定任意时刻时间。通常是由一个事件触发的在这个事件触发之后的一段时间内触发另一个事件,任务可以立即执行。定时任务是有固定周期有明确的触发时间,延时任务是特定时间内会触发。
应用场景有那些:
- 定时发布文章、邮件
- 用户订单下单之后20分钟后,如果用户没有付钱,则由系统自动取消订单;如果在20分钟内期间下单成功,任务取消。
- 接口三方接口出现网络问题,1分钟后重试,如果失败,2分钟重试,直到出现阈值在终止。
快速入门
1.创建Springboot工程添加依赖
java
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--redisson核心依赖-->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.16.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
添加启动类:
java
@SpringBootApplication
@EnableAsync //开启异步注解
public class TestApp {
public static void main(String[] args) {
SpringApplication.run(TestApp.class, args);
}
}
添加配置文件
xml
server:
port: 8001
spring:
application:
name: redisson-test
redis:
host: 127.0.0.1
redisson:
config:
clusterServersConfig:
nodeAddresses:
- "redis://127.0.0.1:6379"
消息发送
java
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private RedissonClient redissonClient;
@GetMapping("/{time}")
public ResponseEntity send(@PathVariable("time") int time) {
// 发送消息到redis
// 需要使用redisson的客户端
RBlockingQueue<String> blockingQueue = redissonClient.getBlockingQueue("test-dqueue");
RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);
delayedQueue.offer("hello", time, TimeUnit.SECONDS);
System.out.println("发送消息完成,延迟时间为: " + time +" 发送时间为: "+new Date());
return ResponseEntity.ok("done");
}
}
消息监听
java
@Service
public class RedisListener {
@Autowired
private TestTasks testTasks;
@PostConstruct // 启动时自动执行该任务
public void handleMessage() throws InterruptedException {
testTasks.handleMessage();
}
}
异步执行任务
java
@Service
@Async
public class TestTasks {
@Autowired
private RedissonClient redissonClient;
public void handleMessage() throws InterruptedException {
RBlockingQueue<String> blockingQueue = redissonClient.getBlockingQueue("test-dqueue");
// 发送一条初始化的消息
RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingQueue);
while (true) {
// 监听消息,如果没有监听到消息,会进入30秒的阻塞状态
String result = blockingQueue.poll(30, TimeUnit.SECONDS);
if (result != null && !result.equals("init")) {
System.out.println("接收到消息: " + result + " " + new Date());
}
}
}
}