Java多线程之Callable,Future,FutureTask

线程可以通过实现Runnable接口,或者继承Thread实现,但是这两种方式在任务执行完成之后无法获取返回结果,于是就有了Callable接口,Future接口与FutureTask类配和来取得返回的结果。

Callable

Callable接口声明了一个方法call(),同时这个方法返回值为V,还可以跑出异常。

Future

Future用来获取异步计算结果,提供以下方法声明

 boolean cancel(boolean mayInterruptIfRunning);
 boolean isCancelled();
 boolean isDone();
 V get() throws InterruptedException, ExecutionException
 V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
复制代码
  • V get() :获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。
  • boolean isDone() :任务结束返回ture;
  • V get(Long timeout , TimeUnit unit) :获取异步执行结果,如果没有结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常。
  • boolean isCancelled() :如果任务完成前被取消,则返回true。
  • boolean cancel(boolean mayInterruptRunning) :用来取消任务,如果任务还没开始,或者任务已经完成,执行cancel(...)方法将返回false;如果任务已经启动,执行cancel(true)方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回true;当任务已经启动,执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回false;mayInterruptRunning参数表示是否中断执行中的线程。

FutureTask

public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>
复制代码

FutureTask类实现了RunnableFuture接口,FutureTask除了实现了Future接口外还实现了Runnable接口。FutureTask类是Future唯一实现类。

使用FutureTask时,根据FutureTask的构造函数可以看到FutureTask既可以接收Callable的实现类,也可以接收Runnable的实现类。当你传入的是Callable的实现类时,可以获取线程执行的结果;传入Runnable的实现类时,由于Runnable的实现没有返回值,需要传入一个你设置的线程完成标识,也就是result,然后当线程结束时会把你传入的result原值返回。

Future与FutureTask分析

我们从ExecutorService接口中submit方法入手,看下AbstractExecutorService类对submit方法的具体实现。

使用submit方法提交任务时,都会通过newTaskFor方法转换成FutureTask对象。

所以ExecutorService接口中submit方法归根结底还是要把你传入的对象封装成FutureTask对象,并通过FutureTask类的内部实现来获取结果的,返回的Future接口对象也要依赖于FutureTask实例化的,所以无论是直接传入自己的Runnable、Callable实现类还是构建FutureTask传入,本质上都是通过FutureTask去实现,没有什么区别。

Future与FutureTask使用

  • future
  • futureTask

猜你喜欢

转载自juejin.im/post/5ca34f88e51d454e5170e507