🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Java `Callable Future`示例 > 原文: [https://howtodoinjava.com/java/multi-threading/java-callable-future-example/](https://howtodoinjava.com/java/multi-threading/java-callable-future-example/) [Java 执行器框架](https://howtodoinjava.com/java/multi-threading/java-thread-pool-executor-example/ "executor")的好处之一是,我们可以运行并发任务,这些并发任务在处理任务后可以返回单个结果。 [Java 并发](https://howtodoinjava.com/java-concurrency-tutorial/) API 通过以下两个接口[`Callable`](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/Callable.html "Callable")和[`Future`](https://docs.oracle.com/javase/10/docs/api/java/util/concurrent/Future.html "Future")实现此目的。 ## 1\. Java `Callable`和`Future`接口 #### 1.1 `Callable` `Callable`接口具有`call()`方法。 在这种方法中,我们必须实现任务的逻辑。 `Callable`接口是一个参数化接口,这意味着我们必须指出`call()`方法将返回的数据类型。 #### 2.2 `Future` `Future`接口具有获取`Callable`对象生成的结果并管理其状态的方法。 ## 2\. Java `Callable Future`示例 在此示例中,我们正在创建类型为`Callable`的`FactorialCalculator`。 这意味着我们将覆盖它的`call()`方法,计算后,我们将从`call()`方法返回结果。 以后可以从主程序保存的`Future`参考中检索此结果。 ```java public class FactorialCalculator implements Callable<Integer> { private Integer number; public FactorialCalculator(Integer number) { this.number = number; } @Override public Integer call() throws Exception { int result = 1; if ((number == 0) || (number == 1)) { result = 1; } else { for (int i = 2; i <= number; i++) { result *= i; TimeUnit.MILLISECONDS.sleep(20); } } System.out.println("Result for number - " + number + " -> " + result); return result; } } ``` 现在,我们使用两个线程和 4 个数字测试上述阶乘计算器。 ```java package com.howtodoinjava.demo.multithreading; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class CallableExample { public static void main(String[] args) { ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2); List<Future<Integer>> resultList = new ArrayList<>(); Random random = new Random(); for (int i=0; i<4; i++) { Integer number = random.nextInt(10); FactorialCalculator calculator = new FactorialCalculator(number); Future<Integer> result = executor.submit(calculator); resultList.add(result); } for(Future<Integer> future : resultList) { try { System.out.println("Future result is - " + " - " + future.get() + "; And Task done is " + future.isDone()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } } //shut down the executor service now executor.shutdown(); } } ``` 程序输出。 ```java Result for number - 4 -> 24 Result for number - 6 -> 720 Future result is - - 720; And Task done is true Future result is - - 24; And Task done is true Result for number - 2 -> 2 Result for number - 6 -> 720 Future result is - - 720; And Task done is true Future result is - - 2; And Task done is true ``` 在这里,我们使用`submit()`方法发送了一个`Callable`对象,该对象将在执行器中执行。 此方法接收`Callable`对象作为参数,并返回一个`Future`对象,我们可以将其用于两个主要目标: 1. **我们可以控制任务的状态** – 我们可以取消任务并检查任务是否完成。 为此,我们使用`isDone()`方法检查任务是否完成。 2. **我们可以通过`call()`方法返回结果**。为此,我们使用了`get()`方法。 该方法一直等到`Callable`对象完成对`call()`方法的执行并返回其结果。 如果在`get()`方法等待结果时线程被中断,则它将引发`InterruptedException`异常。 如果`call()`方法引发异常,则此方法引发`ExecutionException`异常。 `Future`接口提供了`get()`方法的另一个版本,即`get(longtimeout, TimeUnitunit)`。 如果任务的结果不可用,则此版本的`get`方法将等待指定的时间。 如果经过指定的时间段且结果尚不可用,则该方法将返回`null`值。 学习愉快!