Future & FutureTask

一、What

 1. java创建多线程的方式

   a. Thread, 没有执行结果,既没有数据也没有异常

   b. ThreadPool,减少线程创建和销毁的开销

   c. Runnable,只有一个run()方法,没有执行结果,被Thread执行;如果要获得返回结果,可以使用共享变量或者线程通信的方法

   d. Callable,只有一个call()方法,是Runnable的补充,有返回值也有异常,返回的是泛型结果

   e. Future,先生成一个凭据而不是结果,不阻塞接下来的操作,然后通过凭据获取结果,用于异步计算

2. FutureTask类实现了Future接口,是Future的一个基本实现

3. 可以把Callable的实例作为FutureTask的参数,生成一个FutureTask的实例,把这个实例作为Runnable,作为参数启动一个线程

 

二、How

1. Callable接口, 配合ExecutorService里的submit()方法使用,是为了获取返回值

2. Future接口,isDone()方法查看异步操作是否完成,get()方法返回结果,是为了异步

3. FutureTask类

a. 实现了Runnable接口和Future接口,综合了异步和返回结果的功能

b. FutureTask的对象没有返回值,是一个Runnable;但是内部会把Runnable转换为Callable,有返回值;最终的返回值用get()方法获取,而不是直接返回

c. 有一个回调函数done(),任务结束时会被触发;而Future没有此功能,只能判断任务是否结束,然后手动操作

 

 

三、使用场景(When)

1. 耗时计算,主线程完成自己的任务后,再获取子线程的计算结果

2. 高并发环境下只执行一次,例如数据库链接的建立

 

四、Why(原理)

1. FutureTask的状态字段,表示当前线程的状态的转换

* Possible state transitions:
     * NEW -> COMPLETING -> NORMAL
     * NEW -> COMPLETING -> EXCEPTIONAL
     * NEW -> CANCELLED
     * NEW -> INTERRUPTING -> INTERRUPTED
     */
    private volatile int state;
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;

2. FutureTask的run()方法源码,主要逻辑就是执行Callable的call()方法,把结果保存在全局变量里,相当于对Runnable的一次封装

public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable; // 这里的callable是从构造方法里面传人的,虽然FutureTask的实例是Runnable,但最终使用的是Callable
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex); // 保存call方法抛出的异常,而不是直接抛出
                }
                if (ran)
                    set(result); // 保存call方法的执行结果
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

 3. get()方法源码,使用死循环阻塞,直到从全局变量里拿到结果

public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s <= COMPLETING)
            s = awaitDone(false, 0L);
        return report(s);
}

private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            if (Thread.interrupted()) {
                removeWaiter(q);
                throw new InterruptedException();
            }

            int s = state;
            if (s > COMPLETING) {
                if (q != null)
                    q.thread = null;
                return s;
            }
            else if (s == COMPLETING) // cannot time out yet
                Thread.yield();
            else if (q == null)
                q = new WaitNode();
            else if (!queued)
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                     q.next = waiters, q);
            else if (timed) {
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L) {
                    removeWaiter(q);
                    return state;
                }
                LockSupport.parkNanos(this, nanos);
            }
            else
                LockSupport.park(this);
        }
}

 

 

 

参考:

https://www.cnblogs.com/cz123/p/7693064.html

https://www.jianshu.com/p/bce9301f1adb

 

posted @ 2019-09-01 16:51  牧云文仔  阅读(147)  评论(0编辑  收藏  举报