MST

星途 面试题库

面试题:Java NIO异步I/O中Future和FutureTask的区别

在Java NIO异步I/O编程中,常常会用到Future和FutureTask。请阐述它们的主要区别,并且说明在实际应用场景中,何时应该选择使用Future,何时应该选择使用FutureTask。
47.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

主要区别

  1. 概念本质
    • Future:是一个接口,定义了异步计算结果的获取等方法,比如get()获取结果,isDone()判断任务是否完成等。它只是对异步计算结果的一种抽象表示。
    • FutureTask:是一个类,它实现了Future接口和Runnable接口。这意味着它既可以作为一个任务被线程执行,又可以作为异步计算的结果来获取。
  2. 功能侧重
    • Future:侧重于提供获取异步操作结果的方式,以及检查异步操作状态的能力。它本身不包含执行任务的逻辑。
    • FutureTask:除了具备Future获取结果等功能外,还封装了实际的任务执行逻辑。它可以被传递给ExecutorService执行,或者直接由线程执行(因为实现了Runnable接口)。
  3. 创建方式
    • Future:通常是通过ExecutorService.submit()方法返回,例如Future<Integer> future = executorService.submit(() -> { return 1 + 2; }); 这里submit方法会返回一个实现了Future接口的对象。
    • FutureTask:可以直接创建,例如FutureTask<Integer> futureTask = new FutureTask<>(() -> { return 1 + 2; }); 然后可以通过new Thread(futureTask).start();来执行任务。

应用场景选择

  1. 使用Future的场景
    • 当你只关心异步操作的结果,并且该异步操作是通过ExecutorService提交任务时,使用Future较为合适。例如,你有一个线程池ExecutorService,你提交多个任务,只需要获取每个任务的最终结果,不关心任务执行的具体过程和细节,此时ExecutorService.submit()返回的Future就满足需求。
    • 当你使用第三方库提供的异步操作,该库返回Future来表示异步结果时,你只能使用Future来获取结果,例如一些网络异步请求库可能返回Future类型的对象表示请求结果。
  2. 使用FutureTask的场景
    • 当你需要手动控制任务的执行,例如希望在主线程中通过new Thread(futureTask).start();这样的方式来启动任务,而不是依赖ExecutorService时,FutureTask是很好的选择。
    • 当你需要将任务作为一个可复用的组件,既可以作为任务执行,又可以获取异步结果时,FutureTask更合适。比如你有一个复杂的计算任务,在不同的地方可能需要多次执行,同时又要获取执行结果,FutureTask封装这个任务就很方便。