天天看点

和阿里面试官对线FutureTask源码面试(上)1 简介2 案例3 Callable4 Future

1 简介

  • 使用继承方式的好处是方便传参,可在子类里面添加成员变量,通过 set 方法设置参数者通过构造器进行传递
  • 使用 Runnable 方式,则只能使用主线程里面被声明为 final 变量

不好的地方是 Java 不支持多继承,若继承了 Thread 类,则子类不能再继承其它类 ,而 Runable接口则无该限制 。

Thread 类和 Runnable 接口都不允许声明检查型异常,也不能定义返回值。

没有返回值就有点麻烦,这两种方式都没办法拿到任务的返回结果,但FutureTask 可以!

不能声明抛出检查型异常则更麻烦一些。run()方法意味着必须捕获并处理检查型异常。即使小心地保存了异常信息(在捕获异常时)以便稍后检查,但也不能保证这个 Runnable 对象的所有使用者都读取异常信息。

可以修改Runnable实现的getter,让它们都能抛出任务执行中的异常。但这种方法除了繁琐也不是十分安全可靠,你不能强迫使用者调用这些方法,程序员很可能会调用join()方法等待线程结束然后就不管了。

但是现在不用担心了,以上的问题终于在1.5中解决了。

Callable接口和Future接口的引入以及他们对线程池的支持优雅地解决了这两个问题。

2 案例

FutureTask 相关组件如何使用的=

和阿里面试官对线FutureTask源码面试(上)1 简介2 案例3 Callable4 Future

3 Callable

Callable函数式接口定义了唯一方法 - call()。可以在Callable的实现中声明强类型的返回值,甚至抛异常。

利用call()直接返回结果,省去读取值时的类型转换。

  • 定义
  • 和阿里面试官对线FutureTask源码面试(上)1 简介2 案例3 Callable4 Future
  • 返回值是个泛型,使用时,不会直接使用 Callable,而是和 FutureTask 协同。

4 Future

  • Callable 可以返回线程的执行结果,在获取结果时,就需用到Future接口
  • 和阿里面试官对线FutureTask源码面试(上)1 简介2 案例3 Callable4 Future
  • Future是 Java5 中引入的接口,当提交一个Callable对象给线程池时,将得到一个Future对象,并且它和传入的Callable有相同的结果类型声明。

它取代了Java5 前直接操作 Thread 实例做法。以前,不得不用Thread.join()或Thread.join(long millis)等待任务完成。

Future表示异步计算的结果,提供了一些方法来检查计算是否完成,等待其完成以及检索计算结果。

只有在计算完成时才可以使用get方法检索结果,必要时将其阻塞,直到准备就绪。

取消是通过cancel方法执行的。

提供了其他方法来确定任务是正常完成还是被取消。一旦计算完成,就不能取消计算。

如果出于可取消性的目的使用Future而不提供可用的结果,则可以声明Future <?>形式的类型,并作为基础任务的结果返回null。

4.1 Future API

4.1.1 cancel - 尝试取消执行任务

和阿里面试官对线FutureTask源码面试(上)1 简介2 案例3 Callable4 Future

当任务处于不同状态时,该方法有不同响应:

任务已完成 / 已取消 / 由于某些其他原因无法被取消

该尝试会直接失败

尝试成功,且此时任务尚未开始

可以取消成功

任务已开始

mayInterruptIfRunning 参数确定是否可以中断执行该任务的线程以尝试停止该任务。

此方法返回后,对 isDone 的后续调用将始终返回 true。若此方法返回 true,则随后对 isCancelled 的调用将始终返回 true。

4.1.2 isCancelled - 是否被取消

和阿里面试官对线FutureTask源码面试(上)1 简介2 案例3 Callable4 Future

如果此任务在正常完成之前被取消,则返回true.

4.1.3 isDone - 是否完成

和阿里面试官对线FutureTask源码面试(上)1 简介2 案例3 Callable4 Future

如果此任务完成,则返回true。

完成可能是由于正常终止,异常或取消引起的,在所有这些情况下,此方法都将返回true。

4.1.4 get - 获取结果

等待任务完成,然后获取其结果。

和阿里面试官对线FutureTask源码面试(上)1 简介2 案例3 Callable4 Future

若:

  • 任务被取消,抛 CancellationException
  • 当前线程在等待时被中断,抛 InterruptedException
  • 任务抛出了异常,抛 ExecutionException