CompletableFuture vs Future
CompletableFuture可以回调,Future没有回调函数。
AsyncTaskConfig.java
java
package com.xxxx.web.core.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
/**
* 异步任务线程池配置
*/
@Configuration
public class AsyncTaskConfig {
@Bean
public Executor ocrTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("OCR-AsyncTask-");
executor.initialize();
return executor;
}
}
Application.java
java
@SpringBootApplication
@EnableAsync
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(com.miniapp.Application.class, args);
}
}
这里主要就是配置@EnableAsync注解
OcrController.java
java
package com.xxx.web.controller.system.api;
import com.xxx.common.core.domain.AjaxResult;
import com.xxx.system.service.ITesseractOCRService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.concurrent.CompletableFuture;
@Slf4j
@RestController
@RequestMapping("/api/ocr")
public class OcrController {
@Resource
private ITesseractOCRService iTesseractOCRService;
@PostMapping("/testAsync")
public AjaxResult recognizeTextAsync(@RequestParam("file") MultipartFile file) {
log.info("开始recognizeTextAsync任务:{}", file.getOriginalFilename());
CompletableFuture<String> ocrCompletableFuture = iTesseractOCRService.recognizeTextAsync(file);
// 如果执行成功:
ocrCompletableFuture.thenAccept((result) -> log.info("ocr任务结束:{}---{}", file.getOriginalFilename() ,result));
// 如果执行异常:
ocrCompletableFuture.exceptionally((e) -> {
log.error("ocr任务异常结束", e);
return null;
});
log.info("结束recognizeTextAsync任务:{}", file.getOriginalFilename());
return AjaxResult.success();
}
}
这里关键代码就是thenAccept异步任务完成正常回调和exceptionally异步任务执行异常回调。
ITesseractOCRService.java
java
package com.xxxx.system.service;
import org.springframework.web.multipart.MultipartFile;
import java.util.concurrent.CompletableFuture;
/**
* ocr识别服务
*/
public interface ITesseractOCRService {
/**
* ocr识别
* @param multipartFile 上传文件对象
* @return ocr识别字符串
*/
String recognizeText(MultipartFile multipartFile);
/**
* ocr异步识别
* @param multipartFile 上传文件对象
* @return ocr识别字符串
*/
CompletableFuture<String> recognizeTextAsync(MultipartFile multipartFile);
}
TesseractOCRServiceImpl.java
java
package com.xxxx.system.service.impl;
import com.xxx.common.exception.ServiceException;
import com.xxx.system.service.ITesseractOCRService;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.TesseractException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
@Service
@Slf4j
public class TesseractOCRServiceImpl implements ITesseractOCRService {
@Resource
private Tesseract tesseract;
@Override
public String recognizeText(MultipartFile multipartFile) {
try {
BufferedImage image = ImageIO.read(multipartFile.getInputStream());
return tesseract.doOCR(image);
} catch (TesseractException e) {
log.error("OCR识别异常:{}", multipartFile.getOriginalFilename(), e);
throw new ServiceException(String.format("OCR识别异常:%s", multipartFile.getOriginalFilename()));
} catch (IOException e) {
log.error("OCR读文件异常", e);
throw new ServiceException(String.format("OCR读文件异常:%s", multipartFile.getOriginalFilename()));
}
}
@Async("ocrTaskExecutor")
@Override
public CompletableFuture<String> recognizeTextAsync(MultipartFile multipartFile) {
log.info("开始Ocr图片任务{}", multipartFile.getOriginalFilename());
String results = this.recognizeText(multipartFile);
log.info("完成Ocr图片任务{}", multipartFile.getOriginalFilename());
return CompletableFuture.completedFuture(results);
}
}
这里关键代码就是@Async("ocrTaskExecutor")表示方法使用ocrTaskExecutor线程池来运行;CompletableFuture.completedFuture来返回正常异常任务执行完成。
总结
CompletableFuture的回调方式,大大简化了Spring异步任务处理实现。