Runnable:
Runnable的代码非常简单,他是一个接口,且接口中只有一个方法,run(),创建一个类实现他,把一些费时操作写在其中,然后使用某个线程去执行该Runnable实现类即可实现多线程。
Callable:
Callable的代码也非常简单,不同的是他是一个泛型接口,call()函数返回的类型就是创建Callable传进来的V类型,Callable与Runnable的功能大致相同,项目中有些任务是需要异步(提交到线程池中)去执行,而主线程往往需要知道异步执行产生的结果,这时我们要怎么做?用Runnable是无法实现的,我们需要用Callable去实现。
Future:
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException,ExecutionException; V get(long timeOut,@NotNull TimeUnit unit) throws InterruptedException,ExecutionException,TimeoutException; }
Future是一个接口,定义了Future对于具体的Runnable或者Callable任务的执行结果进行取消、查询任务是否被取消,查询是否完成,获取结果、
Future的基本用法:
通过上面的代码并运行:
1、线程是属于异步计算模型,所以你不可能从别的线程中得到方法的返回值,这时候,我们就需要使用Future。
2、Future可以监视目标线程调用Call的情况,当你调用Future的get()方法以获得结果的时候,当前线程就开始阻塞,直接call方法结束返回结果。
3、Future引用对象指向的其实就是FutureTask。
总结:Future可以得到其他线程方法的返回值
FutureTask:
FutureTask的父类是RunnableFuture,而RunnableFuture继承了Runnable和Future两个接口
FutureTask的构造方法:
通过上面的构造函数,我们可以看到,
1、FutureTask最终都是执行Callable类型的任务。
2、如果构造函数参数是Runnable,会被Executors.callable方法转换为Callable类型
下面是Executors.callable方法。
最终返回的是一个RunnableAdapter实例。
继续看看RunnableAdapter的实例。
1、RunnableAdapter是一个FutureTask的一个静态内部类并且实现了Callable,也就是说RunnableAdapter是Callable的一个子类
2、call方法实现代码是,执行Runnable的run方法,并返回构造函数中传入的参数result。
FutureTask的总结:
FutureTask实现两个接口,分为是Future和Runnable,所以它既作为Runnable被线程执行,又可以作为Future得到Callable的返回值,这个组合使用的好处在哪里?
eg:假设有一个很费时逻辑需要计算并返回这个值,同时这个值又不是马上需要,就可以使用这个组合(FutureTask),用另一个线程去计算返回值,而当前线程在使用这个返回值的时候可以进行其他的操作,等到需要这个返回值的时候,再通过Future得到。
注意:通过Executor执行线程任务都是以Callable形式,如果传入Runnable都会转化为Callable。
通过new Thread(runnable),只能是Runnable子类形式