Callable、Future和FutureTask

tags: java concurrent

Callable接口

 public interface Callable {
    V call() throws Exception;
}
  • java1.1推出了Runnable,而Callable是在java1.5被引入
  • 与Runnable相似,有且仅有一个方法,在java 8时被声明为函数式接口
  • 为了解决Runnable不能从执行中返回结果的问题,产生了Callable,相当于在原有功能上增添了结果返回、取消、异常抛出的功能。
  • 运行一个Callable线程有三种方式,你会得到的对象有两种类型,它们是Future和FutureTask

Future接口

 interface Future {
// 获得线程的执行结果
    V get();
// 定义了等待在当前线程中等待结果的最大时间
    V get(long timeout, TimeUnit unit);
// 取消任务, 标记mayInterrupt表示如果任务已经开始并且此刻正在运行,那么应该被中断。
    boolean cancel(boolean mayInterruptIfRunning);
// 检查一个任务是否已经被完成
    boolean isCancelled();
// 检查任务是否被取消
    boolean isDone();
}
  • Future 可以被看作一个整理存储Callable 计算结果的容器。callable 的计算能持续在另一个线程中, 并且任何获取一个Future 结果的尝试都将被阻塞,并且一旦(结果)变得可用,便会返回结果。

Future 提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如果线程没有执行完,Future.get() 方法可能会阻塞当前线程的执行;如果线程出现异常,Future.get() 会 throws InterruptedException 或者 ExecutionException;如果线程已经取消,会跑出 CancellationException。取消由 cancel 方法来执行。isDone 确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明Future 形式类型,并返回 null 作为底层任务的结果。

  • 使用线程池的commit方法运行一个Callable线程,就可以得到一个Future对象:
    ExecutorService es = Executors.newSingleThreadExecutor();
    Callable task = () -> {return "123"};
    Future result = es.submit(task);

FutureTask

  • FutureTask实现了RunnableFuture接口,而RunnableFuture同时继承了Runnable和Future两个接口
  • FutureTask是Future接口的一个唯一实现类。
  • FutureTask提供了2个构造器:
public FutureTask(Callable callable) {}
public FutureTask(Runnable runnable, V result) {}
  • 如果只是运行一个简单的Callable线程,不想配置线程池,可使用Callable构造一个FutureTask对象,并放入Thread中进行start()
  • 当然,也可以使用线程池对一个FutureTask对象进行submit()操作
//第一种方式
ExecutorService executor = Executors.newCachedThreadPool();
Callable task = () -> {return "123"};
FutureTask futureTask = new FutureTask(task);
executor.submit(futureTask);
executor.shutdown();
     
//第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread
Callable task = () -> {return "123"};
FutureTask futureTask = new FutureTask(task);
Thread thread = new Thread(futureTask);
thread.start();

总结

如果你有很多任务要去执行, 并且所有的任务并不依赖前一个的执行结果, 如果你的计算机允许, 你可以使用多线程使用多个处理器同时处理所有的工作。这能够使你的程序执行的更快。

你可能感兴趣的:(Callable、Future和FutureTask)