教你如何判断Java代码中异步操作是否完成

打印 上一主题 下一主题

主题 896|帖子 896|积分 2688

本文分享自华为云社区《java代码实现异步返回结果如何判断异步执行完成》,作者: 皮牙子抓饭。
在许多应用程序中,我们经常使用异步操作来提高性能和响应度。在Java中,我们可以使用多线程或者异步任务来执行耗时操作,并且在后台处理过程完成后获取结果。但是,在使用异步操作时,我们通常需要知道异步任务何时完成,以便进行下一步的操作。 本篇文章将介绍几种常见的方法来判断Java代码中异步操作是否完成。
1. 使用Future和Callable

Java中的Future接口定义了一种方式来表示异步操作的未来结果。我们可以使用Callable接口来定义异步任务,它返回一个Future对象,我们可以利用Future对象的方法来检查任务是否完成。 下面是一个例子:
  1. javaCopy code
  2. import java.util.concurrent.Callable;
  3. import java.util.concurrent.ExecutorService;
  4. import java.util.concurrent.Executors;
  5. import java.util.concurrent.Future;
  6. public class AsyncDemo {
  7.     public static void main(String[] args) throws Exception {
  8.         ExecutorService executorService = Executors.newSingleThreadExecutor();
  9.         // 定义异步任务
  10.         Callable<String> asyncTask = () -> {
  11.             Thread.sleep(2000); // 模拟耗时操作
  12.             return "Async task completed";
  13.         };
  14.         // 提交异步任务
  15.         Future<String> future = executorService.submit(asyncTask);
  16.         // 判断任务是否完成
  17.         while (!future.isDone()) {
  18.             System.out.println("Task not done yet...");
  19.             Thread.sleep(500);
  20.         }
  21.         // 获取结果
  22.         String result = future.get();
  23.         System.out.println(result);
  24.         // 关闭线程池
  25.         executorService.shutdown();
  26.     }
  27. }
复制代码
在上面的代码中,我们创建了一个单线程的ExecutorService来执行异步任务。我们使用submit方法提交异步任务,并得到一个Future对象。然后,我们可以使用isDone()方法来判断任务是否完成,如果任务没有完成,则等待片刻后再次检查。一旦任务完成,我们可以使用get()方法获取任务的结果。
2. 使用CompletableFuture

自Java 8起,Java提供了CompletableFuture类来更加方便地处理异步操作。CompletableFuture是Future的一个实现,同时也支持对未来结果的处理和组合。 下面是一个例子:
  1. javaCopy code
  2. import java.util.concurrent.CompletableFuture;
  3. import java.util.concurrent.TimeUnit;
  4. public class AsyncDemo {
  5.     public static void main(String[] args) throws Exception {
  6.         // 定义异步任务
  7.         CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
  8.             try {
  9.                 TimeUnit.SECONDS.sleep(2); // 模拟耗时操作
  10.             } catch (InterruptedException e) {
  11.                 e.printStackTrace();
  12.             }
  13.             return "Async task completed";
  14.         });
  15.         // 判断任务是否完成
  16.         while (!future.isDone()) {
  17.             System.out.println("Task not done yet...");
  18.             TimeUnit.MILLISECONDS.sleep(500);
  19.         }
  20.         // 获取结果
  21.         String result = future.get();
  22.         System.out.println(result);
  23.     }
  24. }
复制代码
在上述代码中,我们使用supplyAsync方法创建了一个CompletableFuture对象,并定义了异步任务。然后,我们可以使用isDone()方法来判断任务是否完成。通过调用get()方法可以获取最终的结果。
当涉及到实际应用场景时,异步操作的一个常见用例是在Web应用中执行并行的HTTP请求以提高性能。以下是一个示例代码,展示了如何使用异步操作来执行多个HTTP请求,并在所有请求完成后进行处理。
  1. javaCopy code
  2. import java.io.BufferedReader;
  3. import java.io.IOException;
  4. import java.io.InputStreamReader;
  5. import java.net.HttpURLConnection;
  6. import java.net.URL;
  7. import java.util.ArrayList;
  8. import java.util.List;
  9. import java.util.concurrent.*;
  10. public class AsyncHttpExample {
  11.     public static void main(String[] args) throws Exception {
  12.         List<Future<String>> futures = new ArrayList<>();
  13.         
  14.         ExecutorService executor = Executors.newFixedThreadPool(5);
  15.         
  16.         List<String> urls = List.of(
  17.                 "https://www.example.com/api1",
  18.                 "https://www.example.com/api2",
  19.                 "https://www.example.com/api3"
  20.         );
  21.         
  22.         for (String url : urls) {
  23.             Callable<String> task = () -> {
  24.                 return performRequest(url);
  25.             };
  26.             
  27.             Future<String> future = executor.submit(task);
  28.             futures.add(future);
  29.         }
  30.         
  31.         executor.shutdown();
  32.         
  33.         for (Future<String> future : futures) {
  34.             try {
  35.                 String result = future.get();
  36.                 System.out.println("Received response: " + result);
  37.             } catch (InterruptedException | ExecutionException e) {
  38.                 e.printStackTrace();
  39.             }
  40.         }
  41.     }
  42.    
  43.     private static String performRequest(String url) throws IOException {
  44.         HttpURLConnection connection = null;
  45.         BufferedReader reader = null;
  46.         StringBuilder response = new StringBuilder();
  47.         
  48.         try {
  49.             URL requestUrl = new URL(url);
  50.             connection = (HttpURLConnection) requestUrl.openConnection();
  51.             connection.setRequestMethod("GET");
  52.             
  53.             reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
  54.             String line;
  55.             
  56.             while ((line = reader.readLine()) != null) {
  57.                 response.append(line);
  58.             }
  59.         } finally {
  60.             if (connection != null) {
  61.                 connection.disconnect();
  62.             }
  63.             
  64.             if (reader != null) {
  65.                 reader.close();
  66.             }
  67.         }
  68.         
  69.         return response.toString();
  70.     }
  71. }
复制代码
在这个示例中,我们创建了一个固定大小的线程池,并为每个URL创建了一个异步任务。每个任务在自己的线程中执行HTTP请求,并返回响应结果。我们使用Future来跟踪每个任务的执行状态和结果。一旦所有任务都被提交,我们调用shutdown()方法关闭线程池,然后通过迭代每个Future对象,使用get()方法获取任务的结果。最后,我们可以根据需要对结果进行进一步处理,这里只是简单地打印出每个请求的响应。
java.util.concurrent.Callable 是 Java 并发编程中的一个接口,它表示一个可调用的任务,可以在计算中返回一个值。与 Runnable 接口不同,Callable 接口的 call() 方法可以返回一个结果,并且可以在执行过程中抛出受检异常。 Callable 接口定义了以下方法:
<ul>V call() throws Exception:执行任务并返回结果。可以抛出受检异常。
boolean equals(Object obj):比较该 Callable 与指定对象是否相等。
default <U> Callable<U> compose(Function
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

杀鸡焉用牛刀

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表