前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Future备忘录

Future备忘录

作者头像
Oceanlong
发布2019-01-28 17:11:26
3550
发布2019-01-28 17:11:26
举报

概述

Future是一个接口,它的主要目的,是为了我们能够方便的控制在线程中的任务的进度。在实际使用中,它常与Callable一起使用。本文主要为了理清,Java中,线程任务的各种类的关系。

Runable与Callable

Runable与Callable都是纯接口,它是Java中,对于任务的抽象概念。其中,我们看一看它们的源码就可以知道了。

代码语言:javascript
复制
public interface Runnable {
 abstract void run();
}
代码语言:javascript
复制
public interface Callable<V> {

    V call() throws Exception;
}

Runable与Callable的差别就是一个有返回,一个没返回。

Future

Future是线程运行任务的控制器,我们可以通过它,控制任务的启停,获取任务的状态,获取任务返回的结果。

先看源码:

代码语言:javascript
复制
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提供的API。其中,值得注意的是,get方法会阻塞当前线程。

在Java中,提供了一种基本的实现:FutureTask FutureTask实现了RunnableFuture<V>接口,而 RunnableFuture<V>则是继承了,RunnbleFuture<V>

代码语言:javascript
复制
public interface RunnableFuture<V> extends Runnable, Future<V> {
    /**
     * Sets this Future to the result of its computation
     * unless it has been cancelled.
     */
    void run();
}

FutureTask提供了两个构造方法:

代码语言:javascript
复制
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

   
    public FutureTask(Runnable runnable, V result) {
        this.callable = Executors.callable(runnable, result);
        this.state = NEW;       // ensure visibility of callable
    }

其中输入RunnableFutureTask的内部也会转化为Callable

代码语言:javascript
复制
    private static final class RunnableAdapter<T> implements Callable<T> {
        private final Runnable task;
        private final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }

所以,我们使用时,是将需要执行的逻辑放在Callable中,然后 当我们将FutureTask传入线程池,或者新线程时,因为它本身具有Runable的接口,所以可以像正常Runnable那样执行。又因为其持有了一个Callable。所以,当任务执行完时,会有输出结果,FutureTask会保存这个结果,等待外部来取。

如果此时任务尚未执行完成,外部就企图获取结果,会阻塞当前线程。

这个地方看起逻辑复杂,其实只要看一眼源码就很清楚了。

代码语言:javascript
复制
    public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
    }

    public V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (unit == null)
            throw new NullPointerException();
        int s = state;
        if (s <= COMPLETING &&
            (s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
            throw new TimeoutException();
        return report(s);
    }

其中awaitDone就是一个封装了超时和中断的await。 当任务执行完成后,阻塞结果,返回结果。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.01.22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • Runable与Callable
  • Future
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档