线程池系列二:一张动图,彻底懂了execute和submit
我们知道线程池通过execute方法执行提交的Runnable任务,但Runnable只是执行任务,没有返回任何信息。
【线程池原理:线程池原来是个外包公司,打工人我悟了】
若是我们想在异步执行完任务后能够拿到结果。怎么处理呢?
我们可以借助Callable来回去返回结果。线程池为我们提供了另外一种方式执行任务,即submit方法
1、为线程池提交任务
- execute方法执行Runnable任务
- submit方法执行Runnable或Callable任务,且能获取任务返回结果

2、流程分解
2.1、execute方法执行Runnable任务
execute方法将Runnable任务交付给线程池执行
2.2、submit方法执行Runnable或Callable任务
2.2.1、创建futureTask对象(也是Runnable对象),包含属性Callable和object;将futureTask对象引用传递给外部
public class FutureTask<V> implements RunnableFuture<V> {
/**
* 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<V> callable;
/** The result to return or exception to throw from get() */
private Object outcome;
public FutureTask(Callable<V> 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 <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;
}
}
2.2.3、futureTask作为Runnable,execute方法执行此任务(见2.1)
2.2.4、当执行futureTask时,会调用其run方法执行Callable任务
Callable任务若正常返回结果则赋值给object;
若执行异常,则将异常捕获并赋值给object

2.2.5、外部根据futureTask对象引用,调用get()方法,获取到futureTask中的object;
区分是返回结果或异常进行处理
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
通过get()获取结果的过程:
判断任务是否达到最终态。若达到,则根据状态将outcome值区分处理
若未达到
通过LockSupport.parkNanos(futureTask, nanos);挂起当前线程;
futureTask执行到最终态后会执行LockSupport.unpark(thread);重新恢复 因调用get()而挂起的线程
------The End------
如果这个办法对您有用,或者您希望持续关注,也可以扫描下方二维码或者在微信公众号中搜索

线程池系列二:一张动图,彻底懂了execute和submit的更多相关文章
- 线程池系列二:ThreadPoolExecutor讲解
一.简介 1)线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, i ...
- 13张动图助你彻底看懂马尔科夫链、PCA和条件概率!
13张动图助你彻底看懂马尔科夫链.PCA和条件概率! https://mp.weixin.qq.com/s/ll2EX_Vyl6HA4qX07NyJbA [ 导读 ] 马尔科夫链.主成分分析以及条件概 ...
- 《java.util.concurrent 包源码阅读》13 线程池系列之ThreadPoolExecutor 第三部分
这一部分来说说线程池如何进行状态控制,即线程池的开启和关闭. 先来说说线程池的开启,这部分来看ThreadPoolExecutor构造方法: public ThreadPoolExecutor(int ...
- juc线程池原理(二):ThreadPoolExecutor的成员变量介绍
概要 线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析ThreadPoolExecutor类,来了解线程池的原理. ThreadPoolExecutor数据结构 Thread ...
- Java 线程池(二)
简介 在上篇 Java 线程池(一) 我们介绍了线程池中一些的重要参数和具体含义,这篇我们看一看在 Java 中是如何去实现线程池的,要想用好线程池,只知其然是远远不够的,我们需要深入实现源码去了解线 ...
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- Java之线程池(二)
关于线程和线程池的学习,我们可以从以下几个方面入手: 第一,什么是线程,线程和进程的区别是什么 第二,线程中的基本概念,线程的生命周期 第三,单线程和多线程 第四,线程池的原理解析 第五,常见的几种线 ...
- 《java.util.concurrent 包源码阅读》09 线程池系列之介绍篇
concurrent包中Executor接口的主要类的关系图如下: Executor接口非常单一,就是执行一个Runnable的命令. public interface Executor { void ...
- java线程池技术(二): 核心ThreadPoolExecutor介绍
版权声明:本文出自汪磊的博客,转载请务必注明出处. Java线程池技术属于比较"古老"而又比较基础的技术了,本篇博客主要作用是个人技术梳理,没什么新玩意. 一.Java线程池技术的 ...
随机推荐
- vim中字符串的替换
vi/vim 中可以使用 :s 命令来替换字符串 :s/vivian/sky/ 替换当前行第一个 vivian 为 sky :s/vivian/sky/g 替换当前行所有 vivian 为 sky : ...
- node实战小例子
第一章 2020-2-6 留言小本子 思路(由于本章没有数据库,客户提交的数据放在全局变量,接收请求用的是bodyParser, padyParser使用方法 app.use(bodyParser.u ...
- 集合遍历数组三种常用方式(Collecton和Map)
Collection集合遍历数组的三种方式: 迭代器 foreach(增强for循环) JDK1.8之后的新技术Lambda 迭代器: 方法:public Iterator inerator():获取 ...
- HDU2063 过山车(二分匹配)
过山车 HDU - 2063 RPG girls今天和大家一起去游乐场玩,终于可以坐上梦寐以求的过山车了.可是,过山车的每一排只有两个座位,而且还有条不成文的规矩,就是每个女生必须找个个男生做part ...
- 洛谷P1309——瑞士轮(归并排序)
https://www.luogu.org/problem/show?pid=1309#sub 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点 ...
- PHP操作用户提交内容时需要注意的危险函数
对于我们的程序开发来说,用户的输入是解决安全性问题的第一大入口.为什么这么说呢?不管是SQL注入.XSS还是文件上传漏洞,全部都和用户提交的输入参数有关.今天我们不讲这些问题,我们主要探讨下面对用户的 ...
- jmeter之命令行执行jmx脚本
使用界面执行不稳定,且保存报告非常麻烦 https://www.jb51.net/article/191367.htm 作者:Anthony_tester 来源:CSDN 原文:https://blo ...
- Selenium多浏览器并行测试
如果需要同时在IE.firefox.chrome进行测试,可以使用grid. Selenium Grid是一个智能代理服务器,允许Selenium测试将命令路由到远程Web浏览器实例.其目的是提供一种 ...
- 使用Jmeter做接口测试(学生信息的6个接口)
使用Jmeter做接口测试,案例中涉及到接口有:获取学生信息.登录.添加学生信息.学生金币充值.获取所有学生信息.文件上传. 一.获取学生信息(get请求) 服务器名称或IP:输入被请求服务器的名称或 ...
- YbtOJ#532-往事之树【广义SAM,线段树合并】
正题 题目链接:https://www.ybtoj.com.cn/problem/532 题目大意 给出\(n\)个点的一个\(Trie\)树,定义\(S_x\)表示节点\(x\)代表的字符串 求$$ ...