FutureTask源码解析一

本文深入剖析FutureTask,一种可取消的异步计算任务,实现Future接口,代表异步任务的返回结果。介绍了FutureTask的三种状态:未启动、已启动、已完成,以及与之相关的接口如Runnable、Callable、Future和RunnableFuture。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

考虑到文章篇幅过长,分为两篇讲解
本片主要介绍FutureTask涉及的一些接口和基本知识

FutureTask简介
FutureTask是一种可取消的异步计算任务,它实现了Future接口,代表了异步任务的返回结果。从而FutureTask可以启动和取消异步计算任务、查询异步计算任务是否完成和获取异步计算任务的返回结果。只有异步计算任务结束时才能获取返回结果,当异步计算任务还未结束时调用get方法会使线程阻塞。一旦异步计算任务完成,计算任务不能重新启动或者取消,除非调用runAndReset。

FutureTask继承关系图

FutureTask实现了RunnableFuture,RunnableFuture结合了Future和Runnable。

下面对上述接口进行逐个分析
①Runnable接口

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

run方法定义了线程要执行的任务,但无返回值,那么需要返回值又该怎么办? 引入callable接口,callable能返回任务的执行结果。
②Callable接口

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

相对于Runable,Callable具有返回值,可以向上抛出异常,而Runnable的run方法不能抛出异常,只能在方法内部进行catch处理。
③Future接口
Future接口用来代表一个异步操作的执行结果。我们可以用它来获取一个操作的执行结果、取消一个操作、判断一个操作是否已经完成或者是否被取消。

public interface Future<V> {
    // 该方法用来获取执行结果, 如果任务还在执行中, 就阻塞等待
    V get() throws InterruptedException, ExecutionException;
    // 该方法同get方法类似, 不同的是它最多等待指定的时间, 如果指定时间内任务没有完成, 则会抛出TimeoutException异常;
    V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
    // 该方法用来尝试取消一个任务的执行, 它的返回值是boolean类型, 表示取消操作是否成功.
    boolean cancel(boolean mayInterruptIfRunning);
    // 该方法用于判断任务是否被取消了。如果一个任务在正常执行完成之前被cancel掉了, 则返回true
    boolean isCancelled();
    // 如果一个任务已经结束, 则返回true
    // 任务结束包含了以下三种情况,见下面3)
    boolean isDone();
}

根据FutureTask.run()方法被执行的时机,FutureTask可以处于下面3种状态
①未启动
FutureTask.run()方法还没有被执行之前,FutureTask处于未启动状态。
当创建一个FutureTask且没有执行FutureTask.run()方法之前,这个FutureTask处于未启动状态。
②已启动
FutureTask.run()方法被执行的过程中,FutureTask处于已启动状态。
③已完成
FutureTask.run()方法执行完后正常结束或被取消FutureTask.cancel(…),或执行FutureTask.run()方法时抛出异常而结束,FutureTask处于已完成状态。

当FutureTask处于未启动或已启动状态时,执行FutureTask.get()方法将导致调用线程阻塞。
当FutureTask处于已完成状态时,执行FutureTask.get()方法将导致调用线程立即返回结果或抛出异常。
当FutureTask处于未启动状态时,执行FutureTask.cancel()方法将导致此任务永远不会被执行。
当FutureTask处于已启动状态时,执行FutureTask.cancel(true)方法将以中断执行此任务线程的方式来试图停止任务。
注意:线程中断仅仅是置线程的中断状态位,并不会停止线程,需要用户自己去监视线程的状态为并做进一步处理。
当FutureTask处于已启动状态时,执行FutureTask.cancel(false)方法将不会对正在执行此任务的线程产生影响。
注意:此时会让正在执行的任务运行完成。
当FutureTask处于已完成状态时,执行FutureTask.cancel(...)方法将返回false。

④RunnableFuture 接口
RunnableFuture接口同时继承了Runable与Callable接口

public interface RunnableFuture<V> extends Runnable, Future<V> {
    void run(); 
}

FutureTask涉及工具类
①Executors
Executors是一个用于创建线程池的工厂类,同时提供了一些有用的静态方法,比如FutureTask中使用到的接口Executors.callable(runnable, result),此处该类不是重点,不作过多解析,只简单描述与FutureTask相关部分。

public class Executors {
    /**
     * Returns a {@link Callable} object that, when
     * called, runs the given task and returns the given result.  This
     * can be useful when applying methods requiring a
     * {@code Callable} to an otherwise resultless action.
     * @param task the task to run
     * @param result the result to return
     * @param <T> the type of the result
     * @return a callable object
     * @throws NullPointerException if task null
     */
    public static <T> Callable<T> callable(Runnable task, T result) {
        if (task == null)
            throw new NullPointerException();
        return new RunnableAdapter<T>(task, result);
    }
    
    /**
     * A callable that runs given task and returns given result
     */
    static final class RunnableAdapter<T> implements Callable<T> {
        final Runnable task;
        final T result;
        RunnableAdapter(Runnable task, T result) {
            this.task = task;
            this.result = result;
        }
        public T call() {
            task.run();
            return result;
        }
    }
    // RunnableAdapter采用了适配器模式,将一个Runnable类型对象适配成Callable类型。
    // 对于result原样返回并无什么意义,只是适配成Callable需要返回值。
}

②Unsafe
Unsafe 是 sun.misc 包下的一个类,可以直接操作堆外内存,可以随意查看及修改JVM中运行时的数据,使Java语言拥有了类似C语言指针一样操作内存空间的能力。Unsafe 的操作粒度不是类,而是内存地址和所对应的数据,增强了Java语言操作底层资源的能力。后面单独写一篇关于Unsafe使用的文章,此处不是重点,不做解析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值