原文: https://howtodoinjava.com/java/multi-threading/java-callable-future-example/
Java 执行器框架的好处之一是,我们可以运行并发任务,这些并发任务在处理任务后可以返回单个结果。 Java 并发 API 通过以下两个接口Callable和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参考中检索此结果。
public class FactorialCalculator implements Callable<Integer>{private Integer number;public FactorialCalculator(Integer number) {this.number = number;}@Overridepublic 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 个数字测试上述阶乘计算器。
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 nowexecutor.shutdown();}}
程序输出。
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对象,我们可以将其用于两个主要目标:
我们可以控制任务的状态 – 我们可以取消任务并检查任务是否完成。 为此,我们使用
isDone()方法检查任务是否完成。我们可以通过
call()方法返回结果。为此,我们使用了get()方法。 该方法一直等到Callable对象完成对call()方法的执行并返回其结果。
如果在get()方法等待结果时线程被中断,则它将引发InterruptedException异常。 如果call()方法引发异常,则此方法引发ExecutionException异常。
Future接口提供了get()方法的另一个版本,即get(longtimeout, TimeUnitunit)。 如果任务的结果不可用,则此版本的get方法将等待指定的时间。 如果经过指定的时间段且结果尚不可用,则该方法将返回null值。
学习愉快!
