线程池系列二:一张动图,彻底懂了execute和submit


我们知道线程池通过execute方法执行提交的Runnable任务,但Runnable只是执行任务,没有返回任何信息。

【线程池原理:线程池原来是个外包公司,打工人我悟了

若是我们想在异步执行完任务后能够拿到结果。怎么处理呢?

我们可以借助Callable来回去返回结果。线程池为我们提供了另外一种方式执行任务,即submit方法

1、为线程池提交任务

  • execute方法执行Runnable任务
  • submit方法执行Runnable或Callable任务,且能获取任务返回结果
    线程池系列二:一张动图,彻底懂了execute和submit

2、流程分解

2.1、execute方法执行Runnable任务
execute方法将Runnable任务交付给线程池执行

2.2、submit方法执行Runnable或Callable任务
2.2.1、创建futureTask对象(也是Runnable对象),包含属性Callable和object;将futureTask对象引用传递给外部


public class FutureTask implements RunnableFuture {

   /**
     * Possible state transitions:
     * NEW -> COMPLETING -> NORMAL
     * NEW -> COMPLETING -> EXCEPTIONAL
     * NEW -> CANCELLED
     * NEW -> INTERRUPTING -> INTERRUPTED
     */
    private volatile int state;
    /** The underlying callable; nulled out after running */
    private Callable callable;
    /** The result to return or exception to throw from get() */
    private Object outcome;

    public FutureTask(Callable callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;
    }
  }

FutureTask中的状态属性(state)代表任务执行的进度。当任务执行到最终态时,代表任务执行结束。
后面调用get()方法时,判断到最终态才能获取object的值

2.2.2、若传入Runnable任务,将其转为Callable任务,赋值给Callable;

若传入Callable任务,则直接赋值给Callable

public static  Callable callable(Runnable task, T result) {
    if (task == null)
         throw new NullPointerException();
    return new RunnableAdapter(task, result);
}

/**
  * A callable that runs given task and returns given result
  */
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;
     }
 }

2.2.3、futureTask作为Runnable,execute方法执行此任务(见2.1)

2.2.4、当执行futureTask时,会调用其run方法执行Callable任务

Callable任务若正常返回结果则赋值给object;

若执行异常,则将异常捕获并赋值给object

线程池系列二:一张动图,彻底懂了execute和submit

2.2.5、外部根据futureTask对象引用,调用get()方法,获取到futureTask中的object;
区分是返回结果或异常进行处理

public V get() throws InterruptedException, ExecutionException {
        int s = state;
        if (s = CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

通过get()获取结果的过程:

判断任务是否达到最终态。若达到,则根据状态将outcome值区分处理

若未达到

通过LockSupport.parkNanos(futureTask, nanos);挂起当前线程;

futureTask执行到最终态后会执行LockSupport.unpark(thread);重新恢复 因调用get()而挂起的线程

Original: https://www.cnblogs.com/mlwy/p/15448679.html
Author: zy苦行僧
Title: 线程池系列二:一张动图,彻底懂了execute和submit

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/576380/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 02-MySQL关键字、Select语句执行顺序

    SQL关键字 1、分页 MySQL的分页关键词是 limit SELECT * FROM student LIMIT 2,6:查询学生表中的数据,从第三条开始,显示6条数据 2、分…

    数据库 2023年6月16日
    0100
  • MySQL触发器

    触发器 先来个实际的案例 触发器概述 和存储过程一样,都是嵌入在MySQL服务器中的一段程序 触发器由 事件触发,比如INSERT ,UPDATE 等用户的动作或触发某项行为,自动…

    数据库 2023年5月24日
    098
  • 用户管理

    介绍Linux用户组的概念和对用户添加,删除和指定密码的基本操作 用户管理 Linux 系统是一个多用户多任务的操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一…

    数据库 2023年6月16日
    0126
  • SQL的约束

    概念:约束是作用于表中的字段以限制表中数据存储的规则 [En] concept: constraints are rules that act on fields in a tab…

    数据库 2023年5月24日
    0100
  • 1_Maven

    一. 引言 1.1 项目管理问题 项目中jar包资源越来越多, jar包的管理越来越沉重 1.1.1 繁琐 要为每个项目手动导入所需的jar, 需要搜集全部的jar 1.1.2 复…

    数据库 2023年6月11日
    0101
  • Eureka详解系列(四)–Eureka Client部分的源码和配置

    按照原定的计划,我将分三个部分来分析 Eureka 的源码: 今天,我们来研究第二部分的源码。 我的思路是这样子的:先明确 Eureka Client 拥有哪些功能,然后从源码角度…

    数据库 2023年6月6日
    086
  • 慢SQL治理方法论

    @ 一、背景 二、发现 三、定位 四、分析 4.1 索引层面分析 4.2 业务层面分析 五、解决 5.1 SQL优化 5.1.1索引优化 5.1.2 子查询优化 5.1.3 分页优…

    数据库 2023年5月24日
    096
  • 解决PHP undefined function mcrypt_encrypt()的报错问题

    今天迁移服务器代码遇到了一个未定义的错误 查找了相关资料后,发现是缺少php_mcrypt扩展 于是去下载扩展: https://windows.php.net/downloads…

    数据库 2023年6月14日
    089
  • 重返MySQL之MySQL基础

    重返MySQL之MySQL基础 本章详细介绍了,什么是数据库,常见的关系型数据库有哪些,什么是MySQL,及MySQL中DDL操作表,DML操作表记录。 1.0 数据库概述 1.1…

    数据库 2023年6月9日
    0141
  • mysql进阶

    1.二进制格式mysql安装 下载二进制格式的mysql软件包 [root@localhost ~]# cd /usr/src/ [root@localhost src]# wge…

    数据库 2023年5月24日
    090
  • Redis进阶(一)

    通过简单的KV数据库理解Redis 分为访问模块,操作模块,索引模块,存储模块 底层数据结构 除了String类型,其他类型都是一个键对应一个集合,键值对的存储结构采用哈希表 哈希…

    数据库 2023年6月16日
    088
  • Kubeadm部署K8S(kubernetes)集群(测试、学习环境)-单主双从

    1. kubernetes介绍 1.1 kubernetes简介 kubernetes的本质是一组服务器集群,它可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。目的…

    数据库 2023年6月9日
    084
  • Java异步执行器CompletableFuture源码解析

    CompletableFuture是对 Future的一种强有力的扩展, Future只能通过轮询 isDone()方法或者调用 get()阻塞等待获取一个异步任务的结果,才能继续…

    数据库 2023年6月11日
    090
  • OpenSSH制作rpm包和升级OpenSSH过程中遇到的问题

    百度网盘:https://pan.baidu.com/s/1gqpH2xeOkYHJ0CiztbmqoQ 提取码:imfg cp x11-ssh-askpass-1.2.4.1.t…

    数据库 2023年6月14日
    0104
  • Linux网络配置

    Linux网络配置 NAT网络配置 查看网络IP和网关 可以在 编辑->虚拟网络编辑器中 查看网络IP和网关 说明:1.什么是IP协议/地址?即”网络之间能相互连…

    数据库 2023年6月16日
    091
  • web监听器解析

    监听器是web三大组件之一,事件监听机制如下: 事件:某个事件,如果初始化上下文 事件源:事件发生的地方 监听器:一个对象,拥有需要执行的逻辑 注册监听:将事件、事件源、监听器绑定…

    数据库 2023年6月16日
    082
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球