本文分享自华为云社区《java代码实现异步返回结果如何判断异步执行完成》,作者: 皮牙子抓饭。
在许多应用程序中,我们经常使用异步操作来提高性能和响应度。在Java中,我们可以使用多线程或者异步任务来执行耗时操作,并且在后台处理过程完成后获取结果。但是,在使用异步操作时,我们通常需要知道异步任务何时完成,以便进行下一步的操作。 本篇文章将介绍几种常见的方法来判断Java代码中异步操作是否完成。
1. 使用Future和Callable
Java中的Future接口定义了一种方式来表示异步操作的未来结果。我们可以使用Callable接口来定义异步任务,它返回一个Future对象,我们可以利用Future对象的方法来检查任务是否完成。 下面是一个例子:
javaCopy code import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class AsyncDemo { public static void main(String[] args) throws Exception { ExecutorService executorService = Executors.newSingleThreadExecutor(); // 定义异步任务 Callable asyncTask = () -> { Thread.sleep(2000); // 模拟耗时操作 return "Async task completed"; }; // 提交异步任务 Future future = executorService.submit(asyncTask); // 判断任务是否完成 while (!future.isDone()) { System.out.println("Task not done yet..."); Thread.sleep(500); } // 获取结果 String result = future.get(); System.out.println(result); // 关闭线程池 executorService.shutdown(); } }
在上面的代码中,我们创建了一个单线程的ExecutorService来执行异步任务。我们使用submit方法提交异步任务,并得到一个Future对象。然后,我们可以使用isDone()方法来判断任务是否完成,如果任务没有完成,则等待片刻后再次检查。一旦任务完成,我们可以使用get()方法获取任务的结果。
2. 使用CompletableFuture
自Java 8起,Java提供了CompletableFuture类来更加方便地处理异步操作。CompletableFuture是Future的一个实现,同时也支持对未来结果的处理和组合。 下面是一个例子:
javaCopy code import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; public class AsyncDemo { public static void main(String[] args) throws Exception { // 定义异步任务 CompletableFuture future = CompletableFuture.supplyAsync(() -> { try { TimeUnit.SECONDS.sleep(2); // 模拟耗时操作 } catch (InterruptedException e) { e.printStackTrace(); } return "Async task completed"; }); // 判断任务是否完成 while (!future.isDone()) { System.out.println("Task not done yet..."); TimeUnit.MILLISECONDS.sleep(500); } // 获取结果 String result = future.get(); System.out.println(result); } }
在上述代码中,我们使用supplyAsync方法创建了一个CompletableFuture对象,并定义了异步任务。然后,我们可以使用isDone()方法来判断任务是否完成。通过调用get()方法可以获取最终的结果。
当涉及到实际应用场景时,异步操作的一个常见用例是在Web应用中执行并行的HTTP请求以提高性能。以下是一个示例代码,展示了如何使用异步操作来执行多个HTTP请求,并在所有请求完成后进行处理。
javaCopy code import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConn服务器托管网ection; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; public class AsyncHttpExample { public static void main(String[] args) throws Exception { 服务器托管网List> futures = new ArrayList(); ExecutorService executor = Executors.newFixedThreadPool(5); List urls = List.of( "https://www.example.com/api1", "https://www.example.com/api2", "https://www.example.com/api3" ); for (String url : urls) { Callable task = () -> { return performRequest(url); }; Future future = executor.submit(task); futures.add(future); } executor.shutdown(); for (Future future : futures) { try { String result = future.get(); System.out.println("Received response: " + result); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } } private static String performRequest(String url) throws IOException { HttpURLConnection connection = null; BufferedReader reader = null; StringBuilder response = new StringBuilder(); try { URL requestUrl = new URL(url); connection = (HttpURLConnection) requestUrl.openConnection(); connection.setRequestMethod("GET"); reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while ((line = reader.readLine()) != null) { response.append(line); } } finally { if (connection != null) { connection.disconnect(); } if (reader != null) { reader.close(); } } return response.toString(); } }
在这个示例中,我们创建了一个固定大小的线程池,并为每个URL创建了一个异步任务。每个任务在自己的线程中执行HTTP请求,并返回响应结果。我们使用Future来跟踪每个任务的执行状态和结果。一旦所有任务都被提交,我们调用shutdown()方法关闭线程池,然后通过迭代每个Future对象,使用get()方法获取任务的结果。最后,我们可以根据需要对结果进行进一步处理,这里只是简单地打印出每个请求的响应。
java.util.concurrent.Callable是 Java 并发编程中的一个接口,它表示一个可调用的任务,可以在计算中返回一个值。与Runnable接口不同,Callable接口的call()方法可以返回一个结果,并且可以在执行过程中抛出受检异常。Callable接口定义了以下方法:
- V call() throws Exception:执行任务并返回结果。可以抛出受检异常。
- boolean equals(Object obj):比较该Callable与指定对象是否相等。
- default Callable compose(Function super V, ? extends U> var1):将该Callable的结果应用于给定函数,并返回Callable。
- default Callable andThen(Function super V, ? extends V2> var1):将给定函数应用于该Callable的结果,并返回新的Callable。
- default Predicate isEqual(Object var1):返回谓词,用于判断对象是否与这个Callable的结果相等。
- default Supplier toSupplier():返回将该Callable的结果作为值的供应商。 在实际应用中,Callable接口常常与ExecutorService结合使用,通过将Callable对象提交给线程池来执行。线程池会返回一个Future对象,用于跟踪任务的执行状态和获取结果。 以下是一个示例代码,展示了如何使用Callable接口:
javaCopy code import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class CallableExample { public static void main(String[] args) throws Exception { Callable task = () -> { int sum = 0; for (int i = 1; i future = executor.submit(task); // 可以在此处执行其他任务 Integer result = future.get(); // 获取任务的结果,会阻塞直到任务完成 System.out.println("Sum: " + result); executor.shutdown(); } }
在上述示例中,我们创建了一个实现了Callable接口的任务,并将其提交给一个单线程的线程池来执行。我们通过Future对象来获取Callable任务的执行结果,其中get()方法会阻塞当前线程,直到任务完成并返回结果。
总结
通过使用Future和CompletableFuture,我们可以方便地判断Java代码中异步操作的执行是否完成。这样,我们就可以在异步操作完成后获取结果,并且继续进行后续的操作。这种方式提高了代码的响应性和性能,使我们能够更好地处理并发和异步任务。
点击关注,第一时间了解华为云新鲜技术~
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
相关推荐: 小程序制作(超详解!!!)第十六节 小程序的基本架构
1.题目描述 创建一个包含:首页、教学、科研、资讯和关于我们5个标签的小程序,每个标签都有对应的页面、图标和标签文字,点击某个标签将切换到对应的页面,同时该标签的图标和文字颜色都会发生变化页面的标题也发生相应的变化,而其他标签则变为非选中状态。 2.app.j…