赞
踩
异步(Asynchronous)是指在进行多任务处理时,各个任务的执行不依赖于其他任务的完成,无需等待一个操作完成后再开始下一个操作。与之相对的是同步(Synchronous),同步操作需要按顺序执行,每个步骤必须等待前一个步骤完成才能开始。
异步处理的优点包括但不限于:
实现异步编程的技术和框架有很多,根据不同的应用场景和技术栈选择合适的方法,例如:
选择合适的异步处理策略,可以显著提升软件系统的性能和用户体验。
Java并发包中的Future
和Callable
接口提供了基本的异步编程模型。你可以通过ExecutorService
提交一个实现了Callable
的任务,它会返回一个Future
对象。你可以在这个Future
对象上调用get()
方法来获取结果,这个方法会阻塞直到结果可用。
Java
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class AsyncExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<String> task = () -> {
Thread.sleep(2000); // 模拟耗时操作
return "Task completed!";
};
Future<String> future = executor.submit(task);
System.out.println("Doing something else...");
// 非阻塞方式检查结果是否准备好了
while (!future.isDone()) {
Thread.sleep(100);
System.out.println("Waiting for result...");
}
System.out.println(future.get()); // 获取并打印结果
executor.shutdown();
}
}
从Java 8开始,CompletableFuture
为异步编程提供了一个更强大、灵活的API,支持链式调用、组合多个异步操作以及更复杂的异步控制流。
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class AsyncExampleWithCompletableFuture {
public static void main(String[] args) {
CompletableFuture.supplyAsync(() -> {
sleep(2000); // 模拟耗时操作
return "Hello";
}).thenAccept(result -> System.out.println("Result: " + result));
System.out.println("Doing something else concurrently...");
}
private static void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
如果你的项目使用了Spring框架,Spring提供了对异步方法的直接支持。你只需要用@Async
注解标记希望异步执行的方法,并配置一个异步任务执行器(TaskExecutor)。
@SpringBootApplication
@EnableScheduling
@EnableAsync
@MapperScan("com.example.demo.dao")
public class SpringBoot3DemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot3DemoApplication.class, args);
}
}
@Configuration
public class AsyncConfig {
@Bean(name = "myAsyncThreadPool")
public ThreadPoolTaskExecutor asyncThreadPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心线程数
executor.setMaxPoolSize(10); // 最大线程数
executor.setQueueCapacity(200); // 队列大小
executor.setThreadNamePrefix("Async-"); // 线程前缀名
executor.initialize();
return executor;
}
}
@Service
@Slf4j
public class AsyncService {
@Async("myAsyncThreadPool")
public void asyncMethod1() {
log.info("asyncMethod1 start");
try {
//发送短信...
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("发送短信 成功");
}
@Async("myAsyncThreadPool")
public void asyncMethod2() {
log.info("asyncMethod2 start");
try {
//通知物流...
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("通知物流 成功");
}
}
@Slf4j
@RestController
@Tag(name = "测试控制器")
@RequestMapping("test")
public class TestController {
@Resource
private AsyncService asyncService;
@Operation(summary = "下单")
@PostMapping("placeAnOrder")
public CommonResult<String> placeAnOrder() {
// 主线程-》参数校验、扣减库存、优惠券状态更新、创建订单
// 异步线程1-》发送短信
asyncService.asyncMethod1();
// 异步线程2-》通知物流
asyncService.asyncMethod2();
return CommonResult.SUCCESS("下单成功");
}
}
对于更复杂的异步处理需求,特别是需要跨服务通信或解耦不同服务组件的情况,可以考虑引入消息队列(如RabbitMQ、Kafka等)。通过发布-订阅模式或点对点模式,将任务放入队列,由专门的消费者异步处理。
RabbitMQ快速上手以及RabbitMQ交换机的四种模式
总结每种方案的选择取决于具体的应用场景、复杂度和性能要求。简单的异步任务可能仅需使用Future
和Callable
,而复杂的异步流程控制和跨服务通信则可能更适合采用CompletableFuture
或消息队列。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。