Java Callable Future示例

Java Callable Future示例

原文: https://howtodoinjava.com/java/multi-threading/java-callable-future-example/

Java 执行器框架的好处之一是,我们可以运行并发任务,这些并发任务在处理任务后可以返回单个结果。 Java 并发 API 通过以下两个接口CallableFuture实现此目的。

1. Java CallableFuture接口

1.1 Callable

Callable接口具有call()方法。 在这种方法中,我们必须实现任务的逻辑。 Callable接口是一个参数化接口,这意味着我们必须指出call()方法将返回的数据类型。

2.2 Future

Future接口具有获取Callable对象生成的结果并管理其状态的方法。

2. Java Callable Future示例

在此示例中,我们正在创建类型为CallableFactorialCalculator。 这意味着我们将覆盖它的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对象,我们可以将其用于两个主要目标:

  1. 我们可以控制任务的状态 – 我们可以取消任务并检查任务是否完成。 为此,我们使用isDone()方法检查任务是否完成。
  2. 我们可以通过call()方法返回结果。为此,我们使用了get()方法。 该方法一直等到Callable对象完成对call()方法的执行并返回其结果。

    如果在get()方法等待结果时线程被中断,则它将引发InterruptedException异常。 如果call()方法引发异常,则此方法引发ExecutionException异常。

Future接口提供了get()方法的另一个版本,即get(longtimeout, TimeUnitunit)。 如果任务的结果不可用,则此版本的get方法将等待指定的时间。 如果经过指定的时间段且结果尚不可用,则该方法将返回null值。

学习愉快!