Java中的Runnable,Callable,Future,FutureTask的比较

发布时间 - 2026-01-10 23:10:48    点击率:

Java中的Runnable,Callable,Future,FutureTask的比较

Java中存在Runnable、Callable、Future、FutureTask这几个与线程相关的类或者接口,在Java中也是比较重要的几个概念,我们通过下面的简单示例来了解一下它们的作用于区别。

Runnable

其中Runnable应该是我们最熟悉的接口,它只有一个run()函数,用于将耗时操作写在其中, 该函数没有返回值 。然后使用某个线程去执行该runnable即可实现多线程,Thread类在调用start()函数后就是执行的是Runnable的run()函数。Runnable的声明如下 :

@FunctionalInterface
public interface Runnable {
  /**
   * When an object implementing interface <code>Runnable</code> is used
   * to create a thread, starting the thread causes the object's
   * <code>run</code> method to be called in that separately executing
   * thread.
   * <p>
   * The general contract of the method <code>run</code> is that it may
   * take any action whatsoever.
   *
   * @see   java.lang.Thread#run()
   */
  public abstract void run();
}

Callable

Callable与Runnable的功能大致相似,Callable中有一个call()函数,但是 call()函数有返回值 ,而Runnable的run()函数不能将结果返回给客户程序。Callable的声明如下 :

@FunctionalInterface
public interface Callable<V> {
  /**
   * Computes a result, or throws an exception if unable to do so.
   *
   * @return computed result
   * @throws Exception if unable to compute a result
   */
  V call() throws Exception;
}

可以看到,这是一个泛型接口,call()函数返回的类型就是客户程序传递进来的V类型。

Future

Executor就是Runnable和Callable的调度容器,Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。get方法会阻塞,直到任务返回结果(Future简介)。Future声明如下:

* @see FutureTask
 * @see Executor
 * @since 1.5
 * @author Doug Lea
 * @param <V> The result type returned by this Future's {@code get} method
 */
public interface Future<V> {

  /**
   * Attempts to cancel execution of this task. This attempt will
   * fail if the task has already completed, has already been cancelled,
   * or could not be cancelled for some other reason. If successful,
   * and this task has not started when {@code cancel} is called,
   * this task should never run. If the task has already started,
   * then the {@code mayInterruptIfRunning} parameter determines
   * whether the thread executing this task should be interrupted in
   * an attempt to stop the task.
   *
   * <p>After this method returns, subsequent calls to {@link #isDone} will
   * always return {@code true}. Subsequent calls to {@link #isCancelled}
   * will always return {@code true} if this method returned {@code true}.
   *
   * @param mayInterruptIfRunning {@code true} if the thread executing this
   * task should be interrupted; otherwise, in-progress tasks are allowed
   * to complete
   * @return {@code false} if the task could not be cancelled,
   * typically because it has already completed normally;
   * {@code true} otherwise
   */
  boolean cancel(boolean mayInterruptIfRunning);

  /**
   * Returns {@code true} if this task was cancelled before it completed
   * normally.
   *
   * @return {@code true} if this task was cancelled before it completed
   */
  boolean isCancelled();

  /**
   * Returns {@code true} if this task completed.
   *
   * Completion may be due to normal termination, an exception, or
   * cancellation -- in all of these cases, this method will return
   * {@code true}.
   *
   * @return {@code true} if this task completed
   */
  boolean isDone();

  /**
   * Waits if necessary for the computation to complete, and then
   * retrieves its result.
   *
   * @return the computed result
   * @throws CancellationException if the computation was cancelled
   * @throws ExecutionException if the computation threw an
   * exception
   * @throws InterruptedException if the current thread was interrupted
   * while waiting
   */
  V get() throws InterruptedException, ExecutionException;

  /**
   * Waits if necessary for at most the given time for the computation
   * to complete, and then retrieves its result, if available.
   *
   * @param timeout the maximum time to wait
   * @param unit the time unit of the timeout argument
   * @return the computed result
   * @throws CancellationException if the computation was cancelled
   * @throws ExecutionException if the computation threw an
   * exception
   * @throws InterruptedException if the current thread was interrupted
   * while waiting
   * @throws TimeoutException if the wait timed out
   */
  V get(long timeout, TimeUnit unit)
    throws InterruptedException, ExecutionException, TimeoutException;
}

FutureTask

FutureTask则是一个RunnableFuture< V>,而RunnableFuture实现了Runnbale又实现了Futrue< V>这两个接口:

public class FutureTask<V> implements RunnableFuture<V> {
......
}

RunnableFuture


/**
 * A {@link Future} that is {@link Runnable}. Successful execution of
 * the {@code run} method causes completion of the {@code Future}
 * and allows access to its results.
 * @see FutureTask
 * @see Executor
 * @since 1.6
 * @author Doug Lea
 * @param <V> The result type returned by this Future's {@code get} method
 */
public interface RunnableFuture<V> extends Runnable, Future<V> {
  /**
   * Sets this Future to the result of its computation
   * unless it has been cancelled.
   */
  void run();
}

另外FutureTask还可以包装Runnable和Callable< V>, 由构造函数注入依赖。

/**
   * Creates a {@code FutureTask} that will, upon running, execute the
   * given {@code Callable}.
   *
   * @param callable the callable task
   * @throws NullPointerException if the callable is null
   */
  public FutureTask(Callable<V> callable) {
    if (callable == null)
      throw new NullPointerException();
    this.callable = callable;
    this.state = NEW;    // ensure visibility of callable
  }

  /**
   * Creates a {@code FutureTask} that will, upon running, execute the
   * given {@code Runnable}, and arrange that {@code get} will return the
   * given result on successful completion.
   *
   * @param runnable the runnable task
   * @param result the result to return on successful completion. If
   * you don't need a particular result, consider using
   * constructions of the form:
   * {@code Future<?> f = new FutureTask<Void>(runnable, null)}
   * @throws NullPointerException if the runnable is null
   */
  public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;    // ensure visibility of callable
  }

可以看到,Runnable注入会被Executors.callable()函数转换为Callable类型,即FutureTask最终都是执行Callable类型的任务。该适配函数的实现如下 :

/**
   * Returns a {@link Callable} object that, when
   * called, runs the given task and returns the given result. This
   * can be useful when applying methods requiring a
   * {@code Callable} to an otherwise resultless action.
   * @param task the task to run
   * @param result the result to return
   * @param <T> the type of the result
   * @return a callable object
   * @throws NullPointerException if task null
   */
  public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
      throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
  }

RunnableAdapter适配器

/**
   * A callable that runs given task and returns given 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;
    }
  }

由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。

因此FutureTask既是Future、Runnable,又是包装了Callable(如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。

完整示例:

package com.stay4it.rx;

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.concurrent.FutureTask;

public class FutureTest {

  public static class Task implements Runnable {

    @Override
    public void run() {
      // TODO Auto-generated method stub
      System.out.println("run");
    }

  }
  public static class Task2 implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
      System.out.println("call");
      return fibc(30);
    }

  }

   /** 
   * runnable, 无返回值 
   */ 
  public static void testRunnable(){
    ExecutorService executorService = Executors.newCachedThreadPool();

    Future<String> future = (Future<String>) executorService.submit(new Task());
    try {
      System.out.println(future.get());
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    executorService.shutdown();
  }

  /** 
   * Callable, 有返回值 
   */ 
  public static void testCallable(){
    ExecutorService executorService = Executors.newCachedThreadPool();

    Future<Integer> future = (Future<Integer>) executorService.submit(new Task2());
    try {
      System.out.println(future.get());
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    executorService.shutdown();
  }

   /** 
   * FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口, 
   * 另外它还可以包装Runnable(实际上会转换为Callable)和Callable 
   * <V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行 
   * ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。 
   */ 
  public static void testFutureTask(){
    ExecutorService executorService = Executors.newCachedThreadPool();
    FutureTask<Integer> futureTask = new FutureTask<Integer>(new Task2());

    executorService.submit(futureTask);
    try {
      System.out.println(futureTask.get());
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    executorService.shutdown();
  }

   /** 
   * FutureTask则是一个RunnableFuture<V>,即实现了Runnbale又实现了Futrue<V>这两个接口, 
   * 另外它还可以包装Runnable(实际上会转换为Callable)和Callable 
   * <V>,所以一般来讲是一个符合体了,它可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行 
   * ,并且还可以通过v get()返回执行结果,在线程体没有执行完成的时候,主线程一直阻塞等待,执行完则直接返回结果。 
   */ 
  public static void testFutureTask2(){
    ExecutorService executorService = Executors.newCachedThreadPool();
    FutureTask<Integer> futureTask = new FutureTask<Integer>(new Runnable() {

      @Override
      public void run() {
        // TODO Auto-generated method stub
        System.out.println("testFutureTask2 run");
      }
    },fibc(30));

    executorService.submit(futureTask);
    try {
      System.out.println(futureTask.get());
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    executorService.shutdown();
  }



  public static void main(String[] args) {

    testCallable();

  }

  /** 
   * 效率低下的斐波那契数列, 耗时的操作 
   * 
   * @param num 
   * @return 
   */ 
  static int fibc(int num) { 
    if (num == 0) { 
      return 0; 
    } 
    if (num == 1) { 
      return 1; 
    } 
    return fibc(num - 1) + fibc(num - 2); 
  } 

}

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!


# Java中的Runnable、Callable、Future、FutureTask的区别  # Java中的Runnable、Callable、Future、FutureTask对比  # 一文搞懂Runnable、Callable、Future、FutureTask及应用  # 实现了  # 还可以  # 转换为  # 则是  # 这两个  # 返回值  # 是一个  # 可以看到  # 它可以  # 它还  # 上会  # 的是  # 都是  # 几个  # 也会  # 又是  # 中有  # 它是  # 这是一个  # 可以通过 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理  在线制作视频网站免费,都有哪些好的动漫网站?  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  Windows Hello人脸识别突然无法使用  Angular 表单中正确绑定输入值以确保提交与验证正常工作  Laravel如何记录自定义日志?(Log频道配置)  如何为不同团队 ID 动态生成多个“认领值班”按钮  php打包exe后无法访问网络共享_共享权限设置方法【教程】  如何彻底卸载建站之星软件?  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  Laravel如何实现API资源集合?(Resource Collection教程)  iOS UIView常见属性方法小结  Java解压缩zip - 解压缩多个文件或文件夹实例  如何在不使用负向后查找的情况下匹配特定条件前的换行符  Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程  Laravel如何使用Laravel Vite编译前端_Laravel10以上版本前端静态资源管理【教程】  济南网站建设制作公司,室内设计网站一般都有哪些功能?  什么是javascript作用域_全局和局部作用域有什么区别?  合肥制作网站的公司有哪些,合肥聚美网络科技有限公司介绍?  微信小程序 闭包写法详细介绍  EditPlus中的正则表达式 实战(1)  如何快速搭建高效服务器建站系统?  如何快速搭建虚拟主机网站?新手必看指南  Laravel如何使用Passport实现OAuth2?(完整配置步骤)  如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】  免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?  如何将凡科建站内容保存为本地文件?  Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】  如何在Windows虚拟主机上快速搭建网站?  Laravel storage目录权限问题_Laravel文件写入权限设置  Laravel如何实现事件和监听器?(Event & Listener实战)  rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted  猎豹浏览器开发者工具怎么打开 猎豹浏览器F12调试工具使用【前端必备】  成都品牌网站制作公司,成都营业执照年报网上怎么办理?  详解Android——蓝牙技术 带你实现终端间数据传输  香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化  如何在阿里云高效完成企业建站全流程?  Laravel N+1查询问题如何解决_Eloquent预加载(Eager Loading)优化数据库查询  Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧  深圳网站制作平台,深圳市做网站好的公司有哪些?  Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】  如何在服务器上三步完成建站并提升流量?  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  iOS中将个别页面强制横屏其他页面竖屏  如何选择可靠的免备案建站服务器?  浅析上传头像示例及其注意事项  JavaScript模板引擎Template.js使用详解  Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康  免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?  如何在万网自助建站平台快速创建网站?