原文: 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;
}
@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 个数字测试上述阶乘计算器。
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();
}
}
程序输出。
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
值。
学习愉快!