当前位置:首页 > 后端开发 > 正文

java中怎么实现异步

va中实现异步可通过线程池、CompletableFuture、Spring的@Async注解等方式,如使用线程池将任务交由线程池执行,或利用CompletableFuture进行异步编程

Java中,实现异步编程的方式多种多样,每种方式都有其特定的应用场景和优缺点,以下是几种常见的实现异步的方法:

java中怎么实现异步 第1张

方法 描述 优点 缺点
线程(Thread) 通过创建新线程来执行任务 简单直接,易于理解 资源消耗大,频繁创建和销毁线程效率低
线程池(ExecutorService) 使用线程池管理线程,重用线程资源 提高资源利用率,避免频繁创建销毁线程 需要手动管理线程池生命周期
Future与Callable 通过Callable接口和Future对象获取异步执行结果 可以获取任务执行结果,支持异常处理 获取结果时可能阻塞,需要手动管理线程和任务生命周期
CompletableFuture Java 8引入,支持链式调用和组合操作 功能强大,易于组合多个异步操作,非阻塞 学习曲线较陡峭,API相对复杂
Spring @Async注解 在Spring框架中使用@Async注解实现异步 简化异步编程,与Spring集成良好 需要配置线程池,依赖于Spring环境

详细实现方式

线程(Thread)

在Java中,最简单的异步编程方式就是直接创建一个新的线程来执行任务,这种方式适用于简单的异步需求,但不适合高并发或复杂的异步场景。

public class AsyncThread extends Thread { @Override public void run() { System.out.println("当前线程名称: " + this.getName() + " , 执行线程名称: " + Thread.currentThread().getName() + " -hello"); } }

线程池(ExecutorService)

使用线程池可以避免频繁创建和销毁线程的开销,提高系统资源的利用率,Java提供了Executors工厂类来创建不同类型的线程池。

java中怎么实现异步 第2张

Future与Callable

Callable接口允许任务返回结果,并通过Future对象来获取结果,这种方式适用于需要获取异步执行结果的场景。

public void futureTest() throws Exception { System.out.println("main函数开始执行"); ExecutorService executor = Executors.newFixedThreadPool(1); Future<Integer> future = executor.submit(new Callable<Integer>() { @Override public Integer call() throws Exception { System.out.println("===task start==="); Thread.sleep(5000); System.out.println("===task finish==="); return 3; } }); // 这里需要返回值时会阻塞主线程 // Integer result = future.get(); System.out.println("main函数执行结束"); System.in.read(); }

CompletableFuture

CompletableFuture是Java 8引入的一个强大的异步编程工具,支持链式调用和组合操作,能够实现非阻塞的异步编程。

CompletableFuture<Long> completableFuture = CompletableFuture.supplyAsync(() -> factorial(number)); while (!completableFuture.isDone()) { System.out.println("CompletableFuture is not finished yet..."); } long result = completableFuture.get();

Spring @Async注解

在Spring框架中,可以使用@Async注解来实现异步方法,首先需要在启动类上添加@EnableAsync注解,并配置一个线程池。

@EnableAsync @SpringBootApplication public class StartApplication { public static void main(String[] args) { SpringApplication.run(StartApplication.class, args); } } @Configuration @Slf4j public class ThreadPoolConfiguration { @Bean(name = "defaultThreadPoolExecutor", destroyMethod = "shutdown") public ThreadPoolExecutor systemCheckPoolExecutorService() { return new ThreadPoolExecutor(3, 10, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(10000), new ThreadFactoryBuilder().setNameFormat("default-executor-%d").build(), (r, executor) -> log.error("system pool is full!")); } } @Service public class AsyncServiceImpl implements AsyncService { @Async("defaultThreadPoolExecutor") public Boolean execute(Integer num) { System.out.println("线程: " + Thread.currentThread().getName() + " , 任务: " + num); return true; } }

FAQs

Q1: CompletableFuture和Future有什么区别?

A1: CompletableFuture是Future的增强版,提供了更多的API来支持链式调用、组合操作和非阻塞的异步编程,而Future只能通过get()方法阻塞等待结果,且不支持链式调用。

Q2: 如何在Spring中使用@Async注解?

A2: 在Spring中使用@Async注解需要先在启动类上添加@EnableAsync注解,并配置一个线程池,然后在需要异步执行的方法上添加@Async注解,并指定线程池的名称(

java中怎么实现异步 第3张

0