FutureTask 是什么?

本文内容如有错误、不足之处,欢迎技术爱好者们一同探讨,在本文下面讨论区留言,感谢。

简介

Java 中为了编程异步事件,我们使用 Thread 类和 Runnable 接口,它们可以开发并行应用程序。问题是在执行结束时不能返回值。因此,添加了 FutureTaksFutureCallable 类,它们与以前的类具有大致相同的功能,但极大地促进了并行应用程序的开发。由于线程 Thread 只支持 Runnable 构造,于是有了 Future 可以根据 Callable 构建线程。由于 Future 只是一个接口,无法直接创建对象,因此有了 FutureTask 。 请参阅:

  • Future:封装并行调用的类,可以取消任务的执行,确定执行是否已成功完成或出错,以及其他操作;
  • FutureTask:这是 Future 接口的实现,将在并行调用中执行。
  • Callable:用于实现并行执行的接口。它与 Runnable 接口非常相似,但是它不返回任何值,而 Callable 必须在执行结束时返回一个值。
  • ExecutorService:用于在创建线程池,开始和取消管理并行执行的线程。

创建线程的3中方式 ThreadRunnableCallable ,其中 Callable 是有返回结果的,这种特殊性在某种情况下非常有帮助,例如:需要知道每个线程计算金额的多少,那么需要返回结果并进行保存。

使用

概念

  1. FutureTask 实现 Future 接口和 RunnableFuture 接口,意味着可以将 FutureTask 用作 Runnable ,并且可以将其提交给 ExecutorService 进行执行。
  2. 当调用一个 Future.submit() 来提交一个可调用或可运行的对象时,大多数时候 ExecutorService 将创建 FutureTask ,也可以手动创建它。
  3. FutureTask 就像一个latch锁。
  4. FutureTask 表示的计算是通过 Callable 接口实现的。
  5. 它实现了 FutureCallable 接口。
  6. get() 方法的行为取决于任务的状态。如果任务未完成,则 get() 方法将等待或阻塞,直到任务完成。任务完成后,它将返回结果或引发 ExecutionException

构造方法只有两个:

// Creates a FutureTask that will, upon running, execute the given Callable.
// 创建一个FutureTask将在运行时执行给定的Callable。
FutureTask(Callable<V> callable)

// Creates a FutureTask that will, upon running, execute the given Runnable, and arrange that get will return the given result on successful completion.
// 创建一个FutureTask将在运行时执行给定的Runnable,并在获得成功完成后返回给定结果result。
FutureTask(Runnable runnable, V result)
package test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Java 项目如何使用FutureTask例子
 */
public class FutureDemo {

    private static final ExecutorService threadpool = Executors.newFixedThreadPool(3);

    public static void main(String args[]) throws InterruptedException, ExecutionException {

        FactorialCalculator task = new FactorialCalculator(10);
        System.out.println("Submitting Task ...");

        Future future = threadpool.submit(task);

        System.out.println("Task is submitted");

        while (!future.isDone()) {
            System.out.println("Task is not completed yet....");
            Thread.sleep(1); //睡眠1秒
        }

        System.out.println("Task is completed, let's check result");
        long factorial = future.get();
        System.out.println("Factorial of 1000000 is : " + factorial);

        threadpool.shutdown();
    }

    private static class FactorialCalculator implements Callable {

        private final int number;

        public FactorialCalculator(int number) {
            this.number = number;
        }

        @Override
        public Long call() {
            long output = 0;
            try {
                output =  factorial(number);
            } catch (InterruptedException ex) {
                Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
            }

            return output;
        }

        private long factorial(int number) throws InterruptedException {
            if (number < 0) {
                throw new IllegalArgumentException("Number must be greater than zero");
            }
            long result = 1;
            while (number > 0) {
                Thread.sleep(1); // 等待1秒时间模拟计算
                result = result * number;
                number--;
            }
            return result;
        }
    }

}

输出结果:

Submitting Task ...
Task is submitted
Task is not completed yet....
Task is not completed yet....
Task is not completed yet....
Task is completed, let's check result
Factorial of 1000000 is : 3628800
原理

原理是将 Runnable 转换为 Callable

public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
}

采用适配器模式,调用 RunnableAdapter(task, result) 方法来适配

static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
}

通过 Callable 的 call() 调用 Runnable 的 run(),把传入的 T result 作为 Callable 的返回结果;

总结

通过使用 FutureTask 类以及 Callable 和 Futere 接口,异步 Java 任务的编程变得更加容易,避免了实现此类应用程序以前所需的“麻烦”。

参考资料

How to use Future and FutureTask in Java Concurrency with Example(如何通过示例在Java并发中使用Future和FutureTask

Java FutureTask Example Program (Java FutureTask示例程序

Class FutureTask(FutureTask类

what is the advantage of using FutureTask over Callable?(与Callable相比,使用FutureTask有什么优势?

Processamento assíncrono em Java com Future e FutureTask(带有Future和FutureTask的异步Java处理

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FutureTask是一个实现了RunnableFuture接口的类,它继承了Runnable和Future接口。因此,FutureTask既可以被当作一个Runnable来使用,也可以被当作一个Future来使用。 FutureTask实现了Future接口,完成了对Future接口的基本实现。除了实现了Future接口以外,FutureTask还实现了Runnable接口,这意味着它可以交由Executor执行,也可以直接用线程调用执行(futureTask.run())。 FutureTask具有三种执行状态:未启动、已启动和已完成。未启动指的是在调用run()方法之前,FutureTask处于未启动状态。已启动指的是FutureTask对象的run方法正在执行过程中,FutureTask处于已启动状态。已完成指的是FutureTask正常执行结束,或者被取消,或者执行过程中抛出异常而导致中断而结束。 在ThreadPoolExecutor的submit方法中,返回的是一个Future的实现,而这个实现就是FutureTask的一个具体实例。FutureTask帮助实现了具体的任务执行,并与Future接口中的get方法关联起来。 总结起来,FutureTask是一个能够同时担任Runnable和Future角色的类,它可以作为一个任务提交给线程池执行,也可以通过get方法来获取任务执行的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【第十二篇】Java 线程池Future和FutureTask【重点】](https://blog.csdn.net/weixin_42039228/article/details/123198358)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [FutureTask简介](https://blog.csdn.net/u014516601/article/details/125123415)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值