189 8069 5689

Java线程池FutureTask实现原理的示例分析-创新互联

这篇文章将为大家详细讲解有关Java线程池FutureTask实现原理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

创新互联基于成都重庆香港及美国等地区分布式IDC机房数据中心构建的电信大带宽,联通大带宽,移动大带宽,多线BGP大带宽租用,是为众多客户提供专业服务器托管报价,主机托管价格性价比高,为金融证券行业内江服务器托管,ai人工智能服务器托管提供bgp线路100M独享,G口带宽及机柜租用的专业成都idc公司。
前言

线程池可以并发执行多个任务,有些时候,我们可能想要跟踪任务的执行结果,甚至在一定时间内,如果任务没有执行完成,我们可能还想要取消任务的执行,为了支持这一特性,ThreadPoolExecutor提供了 FutureTask 用于追踪任务的执行和取消。

类视图

为了更好的理解FutureTask的实现原理,这里先提供几个重要接口和类的结构,如下图所示:

Java线程池FutureTask实现原理的示例分析

RunnableAdapter

ThreadPoolExecutor提供了submit接口用于提交任务,submit支持Runnable和Callable两种不同的接口,为了提供统一的对外接口,jdk在内部把Runnable给包装成了一个Callable,这一切是通过RunnableAdapter这个适配器来实现的。如下为RunnableAdapter的源码:

static final class RunnableAdapter implements Callable {
    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是Callable 的实现类,实现了call方法,而call方法仅仅是调用task.run(),然后return result,这样就能够确保在内部只需要统一处理Callable接口。

FutureTask实现原理

通过上一小节的了解,我们知道提交的Runnable任务在内部统一被转换为Callable任务。查看submit方法的返回值,为一个Future,实际上这个Futrue为FutureTask实例,通过此实例,调用get方法,可以阻塞当前线程,直到任务运行完毕,返回结果。

整个调用链条如下所示:

worker thread -> futureTask.run() -> callable.call() -> task.run()

如果提交的是Callable任务,则只有前面三个调用。

为了更好的展示整个流程,下面举例演示一遍执行流程。

1、 向线程池submit一个Callable任务(Runnable也会被转为Callable), 这时候Callable被传入一个FutureTask实例中,如下所示:

Java线程池FutureTask实现原理的示例分析

2、线程池使用一个线程,执行这个 FutureTask 任务,

Java线程池FutureTask实现原理的示例分析

线程执行任务过程比较简单,最终会调用Callable.call()或者是 Runnable.run()方法,然后得到一个结果,把结果存储在FutureTask实例的outcome属性中,同时把状态修改为NORMAL,表明任务已经执行完毕,可以获取结果了。

我们假设在执行 callable.call() 过程中有多个线程调用了 同个FutureTask实例的get方法,这时候,这些线程会被阻塞,存于一个栈中, 如下图所示:

Java线程池FutureTask实现原理的示例分析

线程1,2,3调用FutureTask.get方法,由于任务未执行结束,这时候,三个线程都将被阻塞休眠,FutureTask中有一个栈,用于存放等待线程,栈顶指针为 FutureTask.waiters引用,当任务执行完毕后,会迭代唤醒整个栈中的线程,这时候,各个线程都将被唤醒,并且可以顺利拿到任务的执行结果(执行结果存于 FutureTask.outcome)

FutureTask还支持任务的取消功能,这一切都是通过 FutureTask的state状态来协调多个线程的。

关于“Java线程池FutureTask实现原理的示例分析”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。


当前标题:Java线程池FutureTask实现原理的示例分析-创新互联
本文路径:http://cdxtjz.cn/article/dpecep.html

其他资讯