想要将短信推送和微信消息推送的功能变为异步执行。对于这种场景, 可以使用Java的 CompletableFuture
或 Spring的 @Async
注解来实现。
以下是使用 CompletableFuture
的方式:
java
CompletableFuture.runAsync(() -> {
// 短信发送代码
}).exceptionally(ex -> {
ex.printStackTrace();
logger.info("短信发送失败:{}", ex.getMessage());
return null;
});
CompletableFuture.runAsync(() -> {
// 微信模板消息推送代码
}).exceptionally(ex -> {
ex.printStackTrace();
return null;
});
这里的 CompletableFuture.runAsync()
方法将会在新的线程中执行传入的lambda表达式,而 exceptionally
方法用于处理执行中出现的异常。
另一个选项是 Spring 的 @Async
注解,它可以使得方法异步地执行。以下是如何使用这个注解:
- 首先在Spring Boot的主类或配置类中开启异步执行:
java
@Configuration
@EnableAsync
public class AsyncConfiguration {
}
2.然后在需要异步执行的方法上添加 @Async
注解:
java
@Service
public class YourService {
@Async
public void sendSms() {
// 短信发送代码
}
@Async
public void sendWeChatTemplateMsg() {
// 微信模板消息推送代码
}
}
其中,@Async
标注的方法将会在另一个线程中执行。
无论是使用 CompletableFuture
还是 @Async
注解,都可以将耗时的IO操作如发送短信和推送微信消息变为异步执行,从而提高程序的响应速度
例如:通过CompletableFuture 自定义线程池,重构现有代码。
在CompletableFuture
中使用自定义线程池,需要先创建一个ExecutorService
对象,然后将它作为参数传递给CompletableFuture.runAsync()
方法。
下面是如何定义一个固定大小的线程池以及如何在CompletableFuture
使用这个线程池:
java
@Autowired
private SmsSendService smsSendService;
@Autowired
private WeChatSendService weChatSendService;
// 定义一个具有10个线程的线程池
private ExecutorService executorService = Executors.newFixedThreadPool(10);
@PostMapping("/registerViolation")
@Transactional
public AjaxResult registerViolation(@Valid @RequestBody TblViolationRecords tblViolationRecords, BindingResult bindingResult)
{
// ...之前的代码保持不变
CompletableFuture<Void> smsFuture = CompletableFuture.runAsync(() -> {
try {
String smsResult = smsSendService.sendSms(mobiles, content);
// ...记录及处理短信发送结果的代码
} catch (Exception e) {
e.printStackTrace();
logger.error("短信发送失败:{}", e.getMessage());
}
}, executorService);
CompletableFuture<Void> weChatFuture = CompletableFuture.runAsync(() -> {
try {
// 获取 wxAccessToken
String wxAccessToken = weChatSendService.getWXAccessToken();
// ...推送微信模板消息的代码
} catch (Exception e) {
e.printStackTrace();
}
}, executorService);
CompletableFuture.allOf(smsFuture, weChatFuture).join();
return AjaxResult.success();
}
在这里,我们在类的字段中定义了一个ExecutorService
的实例executorService
,它由Executors.newFixedThreadPool(10)
生成,表示最多有10个线程被同时执行。然后我们将executorService
作为第二个参数传递给CompletableFuture.runAsync()
的方法,这样,CompletableFuture
就会在我们的线程池中执行任务了。
将自定义线程池作为参数传递给CompletableFuture.runAsync()
方法,可以更好地控制线程的执行。你可以根据应用程序的需求,调整线程池的大小。
注意:你需要在应用程序关闭或不再需要使用线程池时,调用ExecutorService.shutdown()
方法来关闭线程池,释放资源。你可以通过Spring的@PreDestroy
注解,在Bean销毁时关闭线程池:
java
@PreDestroy
public void destroy() {
if (executorService != null) {
executorService.shutdown();
}
}