文章目录
- 一、Future 接口
- 1、Future 接口简介
- 2、取消任务方法
- 3、Future 接口源码注释
- 二、Callable 接口
- 三、Runnable 接口
上一篇博客 【Android 异步操作】AsyncTask 异步任务 ( FutureTask 模拟 AsyncTask 执行过程 | AsyncTask 执行过程回顾 | FutureTask 分析 ) 中 , 使用 FutureTask 模拟 AsyncTask 执行 , 简单介绍了 FutureTask<V> 类 , 和 RunnableFuture<V> 接口 ;
本篇博客将分析 Future 接口 , 和 Runnable 接口 , 以及 FutureTask 的运行机制 ;
相关参考文档 :
- FutureTask
- RunnableFuture
- Future
- Runnable
- Callable
FutureTask 实现了 RunnableFuture 接口 , RunnableFuture 接口实现了 Future 接口和 Runnable 接口 , FutureTask 创建时传入 Callable 对象 , 该对象的 call() 方法就是在子线程执行的异步方法 ;
一、Future 接口
1、Future 接口简介
Future 作用 : Future 是 异步计算结果 ;
提供了以下方法 :
- 检查计算是否完成
- 检查计算是否取消
- 等待计算完成 , 获取计算结果
- 取消任务
获取结果有如下两个条件 :
- 调用 get() 方法获取计算结果
- 计算必须执行完成 , 否则会阻塞直到计算完成 , 才能解除阻塞
调用 get() 方法获取计算结果 , 如果计算没有完成 , 该方法会阻塞 , 直到计算完成之后 , 阻塞才会解除 , 同时返回执行结果 ;
取消任务执行 : 调用 cancel() 方法 , 可以取消异步任务的执行 ; 如果计算完毕 , 该任务无法被取消 ;
使用 Future 的可取消性 : 如果想要 使用 Future 的可取消的特性 , 不提供可用结果 , 可以将类型声明为 Future<?> , 并返回 null 作为基础任务的结果 ;
2、取消任务方法
boolean cancel(boolean mayInterruptIfRunning) 方法 : 尝试取消任务的执行 ;
① 取消失败 : 如果任务已经完成 , 或 已经被取消 , 或 因为其它原因 不能被取消 , 该尝试可能会失败 ;
② 取消成功 : 如果取消成功 , 并且该任务在取消时还没有开始执行 , 该任务之后也不会被执行 ;
③ boolean mayInterruptIfRunning 参数 : 如果任务已经开始执行 , mayInterruptIfRunning 参数确定 , 在尝试终止任务时 , 该执行任务的线程 , 是否应该被中断 ;
④ 方法返回值 : 该方法返回时有以下行为 ;
- 在这之后如果调用 isDone() 方法 , 会返回 true , 说明该任务已经执行完成 ;
- 在这之后如果调用 isCancelled() 方法 , 会返回 true , 表明该任务已经被取消 ;
3、Future 接口源码注释
代码语言:javascript复制package java.util.concurrent;
/**
* Future 是异步计算结果 ;
* 提供了以下方法 : 检查计算是否完成 , 检查计算是否取消 , 获取计算结果 , 取消任务 ;
*
* 获取结果有如下两个条件 : 调用 get() 方法获取计算结果 ,
* 计算必须执行完成 , 否则会阻塞直到计算完成 , 才能解除阻塞 ;
*
* 取消任务执行 : 调用 cancel() 方法 , 可以取消异步任务的执行 ; 如果计算完毕 , 该任务无法被取消 ;
* 使用 Future 的可取消性 : 如果想要使用 Future 的可取消的特性 , 不提供可用结果 ,
* 可以将类型声明为 Future<?> , 并返回 null 作为基础任务的结果 ;
*/
public interface Future<V> {
/**
* 尝试取消任务的执行 ;
* 如果任务已经完成 , 或已经被取消 , 或因为其它原因不能被取消 , 该尝试可能会失败 ;
* 如果取消成功 , 并且该任务在取消时还没有开始执行 , 该任务之后也不会被执行 ;
* 如果任务已经开始执行 , mayInterruptIfRunning 参数确定 , 在尝试终止任务时 ,
* 该执行任务的线程 , 是否应该被中断 ;
* 该方法返回时
* - 在这之后如果调用 isDone() 方法 , 会返回 true , 说明该任务已经执行完成 ;
* - 在这之后如果调用 isCancelled() 方法 , 会返回 true , 表明该任务已经被取消 ;
*
* @param mayInterruptIfRunning
* true 执行该任务的线程应该被中断 ;
* false 执行中的线程应该被执行完成 ;
*
* @return 任务无法取消时会返回 false , 一般是任务已经执行完成 ;
* 成功取消任务 , 返回 true ;
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* 如果任务在正常完成前被取消 , 就返回 true ;
*/
boolean isCancelled();
/**
* 如果任务执行完毕 , 返回 true ;
* 影响任务执行的因素 :
* - 正常终止
* - 出现异常
* - 用户取消
* 上述所有情况出现 , 都表示任务执行完毕 ;
*/
boolean isDone();
/**
* 等待任务完成 , 返回执行结果 ;
*/
V get() throws InterruptedException, ExecutionException;
/**
* 等待任务完成 , 返回执行结果 ;
*
* @param 最长等待时间
* @param 等待时间单位
* @return 任务执行结果
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
二、Callable 接口
Callable<V> 简介 : Callable 是一个任务 , 返回 V 类型结果 , 或者 抛出异常 ; 实现类需要实现 call() 方法 , 该方法没有参数 ;
Callable<V> 与 Runnable 对比 :
- 该 Callable 接口与 Runnable 接口类似 , 两个接口都设计为实现类的对象实例 , 可能都要 在另外的线程执行 ;
- Runnable 接口的 run() 方法 不返回返回值 , 不能抛出检查出的异常 ;
- Callable<V> 接口的 call() 方法可以 返回返回值 , 可以抛出异常 ;
package java.util.concurrent;
/**
* Callable<V> 是一个任务 , 返回 V 类型结果 , 或者抛出异常 ;
* 实现类需要实现 call() 方法 , 该方法没有参数 ;
*
* 该 Callable<V> 接口与 Runnable 接口类似 ,
* 两个接口都设计为实现类的对象实例 , 可能都要在另外的线程执行 ;
*
* Runnable 接口的 run() 方法不返回返回值 , 不能抛出检查出的异常 ;
*/
@FunctionalInterface
public interface Callable<V> {
/**
* 计算出一个结果 , 如果无法完成 , 抛出异常 ;
*/
V call() throws Exception;
}
三、Runnable 接口
Runnable 接口作用 : Runnable 接口的实现类实例 , 需要在一个线程中被执行 ; 该实现类必须实现 run() 方法 , 该方法返回值和参数都是 void ;
Runnable 接口设计 :
- 设计原则 : 该接口被设计为 , 为那些处于活动状态的对象 , 并且这些对象想要执行代码 , 提供一个通用协议 ;
- 如 : Thread 类实现了 Runnable 方法 ;
- 活动状态 : 处于活动状态的含义是 , 线程已经被开始了 , 还不能被停止 , 如果想要执行代码 , 必须在其它线程中执行 ;
创建线程优先策略 :
- 创建线程 : Runnable 为类提供了不需要继承 Thread 类 , 之外的活动的途径 ; 一个类实现了 Runnable 接口 , 在不继承 Thread 的前提下运行 , 方法是将其传入 Thread 构造函数 ;
- 推荐方案 :在大部分情况下 , 如果你只打算去覆盖 run 方法 , 并且没有其它的方法 , 应该使用 Runnable 接口 , 不建议使用 Thread 类 ;
不要轻易去继承一个类 , 除非开发者想要去修改或者增强父类的某些行为 ;
代码语言:javascript复制/**
* Runnable 接口的实现类实例 , 需要在一个线程中被执行 ;
* 该实现类必须实现 run() 方法 , 该方法返回值和参数都是 void ;
*
* 该接口被设计为 , 为那些处于活动状态的对象 , 并且这些对象想要执行代码 , 提供一个通用协议 ;
* 如 : Thread 类实现了 Runnable 方法 ;
* 处于活动状态的含义是 , 线程已经被开始了 , 还不能被停止 , 如果想要执行代码 , 必须在其它线程中执行 ;
*
* 另外 , Runnable 为类提供了不需要继承 Thread 类 , 之外的活动的途径 ;
* 一个类实现了 Runnable 接口 , 在不继承 Thread 的前提下运行 , 方法是将其传入 Thread 构造函数 ;
* 在大部分情况下 , 如果你只打算去覆盖 run 方法 , 并且没有其它的方法 ,
* 应该使用 Runnable 接口 , 不建议使用 Thread 类 ;
*
* 类不应该继承一个类 , 除非开发者想要去修改或者增强父类的某些行为 , 这是很重要的 ;
*/
@FunctionalInterface
public interface Runnable {
/**
* 当一个对象实现了 Runnable 接口 , 用于创建一个线程时 ,
* 启动线程会在该线程中 , 调用该对象的 run() 方法 ;
*
* run() 方法的通用规则是 , 在该方法中可以执行任何操作 ;
*/
public abstract void run();
}