daicy
发布于 2020-04-17 / 1044 阅读
0
0

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示例

在此示例中,我们正在创建FactorialCalculator类型为的Callable。这意味着我们将覆盖它的call()方法,并且在计算之后,我们将从call()方法返回结果。以后可以从Future主程序保存的引用中检索此结果。

FactorialCalculator.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个数字测试上面的阶乘计算器。

CallableExample.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();
      }
}

程序输出。

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

在这里,我们Callable使用该submit()方法发送了要在执行程序中执行的对象。此方法接收一个Callable对象作为参数,并返回一个Future可以用于两个主要目标的对象–

  • 我们可以控制任务的状态 –我们可以取消任务并检查任务是否完成。为此,我们使用了该isDone()方法来检查任务是否完成。
  • 我们可以通过call()方法获得返回的结果。为此,我们使用了该get()方法。该方法一直等到Callable对象完成该call()方法的执行并返回其结果。
    如果线程在get()方法等待结果时被中断,则它将引发InterruptedException异常。如果该call()方法引发异常,则此方法引发ExecutionException异常。

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

参考:http://images.zthinker.com/archives/15507075


评论