JDK:Callable Future FutureTask的区别

  在JDK中,我们可以通过以下方式新开线程并执行:

1.继承Thread类,并重写run()方法 

public class MyThread extends Thread {
    @Override
    public void run() {
        //开发业务需求
    }
}

2.实例化Thread的对象,并传递Runnable实现类的对象

Runnable runnable = new Runnable() {
    public void run() {
        // 开发业务需求
    }
};
Thread thread = new Thread(runnable);
thread.start();

3.使用JDK提供的线程池执行线程

// 用Executors类提供的相关方法生成
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new Runnable() {
    public void run() {
        // 开发业务需求
    }
});

 

在开发程序过程中,我们可能在线程运行的同时需要获取到线程的执行结果,一般有以下3种方式实现:

1.继承Thread类并重写run()方法 或者 传递Runnable实现类的对象,这种需要定义接口来实现,而这对代码的耦合度比较高,需要在接入业务外的代码。

2. 使用JDK提供的线程池来执行线程,通过submit()返回Future类,Future类可以调用get()获取到结果。

3.使用JDK提供的FutureTask类来实现。

本文主要讲解第三种方式实现,一般的实现代码如下:

FutureTask<String> task = new FutureTask<String>(new Callable<String>() {
    public String call() {
        try {
            Thread.sleep(5000);
            // ... do something
        } catch (Exception e) {

        }
        return "Hello world";
    }
});
new Thread(task).start();
try {
    System.out.println(task.get());
} catch (Exception e) {

}

 

下面开始讲解 JDK中的 Callable、Future、FutureTask三个类

public interface Callable<V> {
    
    V call() throws Exception;

}

Callable接口定义了call()

Callable接口可以看作是Runnable接口的升级版,定义了获取运行结果的方法。

 

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接口定义了一组异步计算的方法:

cancel():尝试取消执行当前任务,当任务未执行时直接取消,执行正在执行时,mayInterruptIfRunning参数决定是否中断

get():需要检测当前任务是否完成,已完成则返回结果,未完成需要wait直到任务完成。

 

接下来重点讲解下FutureTask类

public class FutureTask<V> implements RunnableFuture<V> {
}

FutureTask类实现了RunnableFuture接口

public interface RunnableFuture<V> extends Runnable, Future<V> {
}

RunnableFuture接口继承Runnable接口,Future接口

 

new Thread(task).start();

当线程启动的时候,调用FutureTask的run()方法

1.run()

public void run() {

    // 任务不处于初始化状态 或者 当前任务的runner不为null,表明当前任务已开始
    if (state != NEW ||
        !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         null, Thread.currentThread()))
        return;
    
    try {
        Callable<V> c = callable;
        if (c != null && state == NEW) {
            V result;
            boolean ran;
            try {
                // 执行开发者重写的call方法
                result = c.call();
                ran = true;
            } catch (Throwable ex) {
                // 当call方法抛出异常
                result = null;
                ran = false;
                // 1.1
                setException(ex);
            }
            // call方法顺利执行完成
            if (ran)
                // 1.2
                set(result);
        }
    } finally {
        // runnable记录第一个执行run()的thread对象 通过CAS防止run()被同时调用
        // 当state改变时 runnable=null
        runner = null;
        int s = state;
        if (s >= INTERRUPTING)
            // 1.3
            handlePossibleCancellationInterrupt(s);
    }
}

1.1 setException(Throwable t)

// run()遇到Exception时调用
protected void setException(Throwable t) {
    // 将当前任务的状态设置为COMPLETING状态
    if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        outcome = t;
        // 将当前任务设置为最终状态 EXCEPTIONAL
        UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
        // 1.1.1
        finishCompletion();
    }
}

1.2  set(V v)

// run()成功执行后调用
protected void set(V v) {
     // 设置当前状态为COMPLETING状态
     if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
        // 记录结果
        outcome = v;
        // 设置当前状态为最终状态NORMAL
        UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
        // 1.1.1
        finishCompletion();
     }
}

1.1.1 finishCompletion()

// 任务执行完 或者 取消后调用
private void finishCompletion() {
    // assert state > COMPLETING;
    // WaitNode类
    // static final class WaitNode {
    //    volatile Thread thread;
    //    volatile WaitNode next;
    //    WaitNode() { thread = Thread.currentThread(); }
    // }
    // WaitNode对象 用单链表来记录哪个线程调用get()
    // 通过CAS自旋锁将当前waiters对象置为null
    for (WaitNode q; (q = waiters) != null;) {
        if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
            // 遍历链表
            for (;;) {
                Thread t = q.thread;
                if (t != null) {
                    q.thread = null;
                    // 恢复线程执行
                    LockSupport.unpark(t);
                }
                WaitNode next = q.next;
                if (next == null)
                    break;
                q.next = null; // unlink to help gc
                q = next;
            }
            break;
        }
    }

    done();

    callable = null;
}

2.1 get()

public V get() throws InterruptedException, ExecutionException {
    int s = state;
    // 如果当前任务状态处于 NEW || COMPLETING 则将进入等待队列
    if (s <= COMPLETING)
        // 2.2
        s = awaitDone(false, 0L);
    // 2.3
    return report(s);
}

2.2  awaitDone(boolean timed, long nanos)

private int awaitDone(boolean timed, long nanos)
        throws InterruptedException {
        final long deadline = timed ? System.nanoTime() + nanos : 0L;
        WaitNode q = null;
        boolean queued = false;
        for (;;) {
            // 如果当前线程被中断  将当前的waitNode从等待栈移除
            if (Thread.interrupted()) {
                // 2.2.1
                removeWaiter(q);
                throw new InterruptedException();
            }
            
            // 如果此时当前任务状态为已完成||取消 则直接返回得到结果
            int s = state;
            if (s > COMPLETING) {
                if (q != null)
                    q.thread = null;
                return s;
            }
            // 如果此时任务状态为完成中  则将线程的时间片让掉 等待下一轮分配CPU分配时间片
            else if (s == COMPLETING) // cannot time out yet
                Thread.yield();
            else if (q == null)
                q = new WaitNode();
            else if (!queued)
                // 将当前的waitNode加入等待栈 插入作为头部
                queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                     q.next = waiters, q);
            else if (timed) {
                nanos = deadline - System.nanoTime();
                // 如果设置为定时模式并且当前时间超过设置的时间 立即返回
                if (nanos <= 0L) {
                    // 2.2.1
                    removeWaiter(q);
                    return state;
                }
                // 使用UnSafe类挂起线程nanos毫秒
                LockSupport.parkNanos(this, nanos);
            }
            else
                // 使用UnSafe类挂起线程
                LockSupport.park(this);
        }
    }

2.2.1 removeWaiter(WaitNode node)

//删除指定节点 Treiber算法无锁删除节点
private void removeWaiter(WaitNode node) {
    if (node != null) {
        //将WaitNode的线程置为null,根据thread是否为null判断是否要把node移出
        node.thread = null;
        retry:
        for (;;) {
            for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
                s = q.next;
                // pred记录当前node的上个节点
                if (q.thread != null)
                    pred = q;
                // 执行到这里说明 q.thread为null 节点node是需要删除的节点
                else if (pred != null) {
                    // 将上个节点指向下个节点
                    pred.next = s;
                    // pred.thread为null  有其他线程也在执行removeWaiter方法 重新从外层循环执行
                    if (pred.thread == null) // check for race
                        continue retry;
                }
                // 执行到这里说明 WaitNode在栈顶 通过CAS将node的下个节点赋给waiters
                else if (!UNSAFE.compareAndSwapObject(this, waitersOffset, q, s))
                    continue retry;
            }
            break;
        }
    }
}

2.3 report(int s)

private V report(int s) throws ExecutionException {
    Object x = outcome;
    // 当前任务状态为成功正常  将结果返回
    if (s == NORMAL)
        return (V)x;
    // 当前任务被取消 抛出CancellationException
    if (s >= CANCELLED)
        throw new CancellationException();
    // 执行到这里  任务处于NEW COMPLETING EXCEPTIONAL则抛出ExecutionException
    throw new ExecutionException((Throwable)x);
}

总结:

Callable接口定义了可获取方法结果,可以看作是Runnable接口的升级版。

Future接口定义了针对任务操作的一系列接口。

FutureTask类是Future接口、Runnable接口的实现类,旨在提供针对任务的操作的实现。当线程启动时,将任务的runnable线程设置为执行线程,防止被其他线程启动(FutureTask类实例对象只能被一个线程执行),执行期间,调用get()将进入等待队列并将所在线程挂起,执行完毕,将等待队列的线程恢复,返回结果。

 

在FutureTask源码中我们看到很多Unsafe调用的方法,对Unsafe不了解可戳>>Unsafe类

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值