Java中中Future、、FutureTask原理以及与线程池的搭配使用原理以及与线程池的搭配使用
主要为大家详细介绍了Java中Future、FutureTask原理以及与线程池的搭配使用,具有一定的参考价值,感兴
趣的小伙伴们可以参考一下
Java中的Future和Future通常和线程池搭配使用,用来获取线程池返回执行后的返回值。我们假设通过Executors工厂方法构
建一个线程池es ,es要执行某个任务有两种方式,一种是执行 es.execute(runnable) ,这种情况是没有返回值的; 另外一种情
况是执行 es.submit(runnale)或者 es.submit(callable) ,这种情况会返回一个Future的对象,然后调用Future的get()来获取返回
值。
Future
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
Future是一个接口,他提供给了我们方法来检测当前的任务是否已经结束,还可以等待任务结束并且拿到一个结果,通过调用
Future的get()方法可以当任务结束后返回一个结果值,如果工作没有结束,则会阻塞当前线程,直到任务执行完毕,我们
可以通过调用cancel()方法来停止一个任务,如果任务已经停止,则cancel()方法会返回true;如果任务已经完成或者已
经停止了或者这个任务无法停止,则cancel()会返回一个false。当一个任务被成功停止后,他无法再次执行。isDone()
和isCancel()方法可以判断当前工作是否完成和是否取消。
线程池中有以下几个方法:
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
都返回一个Future对象,仔细查看发现,所有的方法最终都将runnable或者callable转变成一个RunnableFuture的对象,这个
RunnableFutre的对象是一个同时继承了Runnable和Future的接口
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
然后调用executor(runnable)方法,关于executor(runnable)的具体实现我们后面再讲。最后返回一个RunnableFuture对象。
RunnableFuture这个接口直有一个具体的实现类,那就时我们接下来要讲的FutureTask。
FutureTask
public class FutureTask<V> implements RunnableFuture<V>
FutureTask实现了RunnableFuture的接口,既然我们知道最终返回的是一个FutureTask对象ftask,而且我们可以通过
ftask.get()可以的来得到execute(task)的返回值,这个过程具体事怎么实现的了??这个也是本篇文章的所要讲的。
我们可以先来猜测一下它的实现过程,首先Runnable的run()是没有返回值的,所以当es.submit()的参数只有一个Runnable对
象的时候,通过ftask.get()得到的也是一个null值,当参数还有一个result的时候,就返回这个result;如果参数是一个Callable
的对象的时候,Callable的call()是有返回值的,同时这个call()方法会在转换的Runable对象ftask的run()方法中被调用,然后将
它的返回值赋值给一个全局变量,最后在ftask的get()方法中得到这个值。猜想对不对了? 我们直接看源码。
评论0