Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask
多线程一直是初学者最抵触的东西,如果你想进阶的话,那必须闯过这道难关,特别是多线程中Thread、Runnable、Callable、Future、FutureTask这几个类往往是初学者容易搞混的。这里先总结这几个类特点和区别,让大家带着模糊印象来学习这篇文章
- Thread、Runnable、Callable:都是线程
- Thread特点:提供了线程等待、线程睡眠、线程礼让等操作
- Runnable和Callable特点:都是接口,并提供对应的实现方法
- Runnable、Callable区别:Runnable无返回值,Callable有返回值
- Future:提供了对Runnable和Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果等操作
- FutureTask:Runnable和Future的结合体,即拥有Future的特性
我们对线程的使用,经常有这两种写法
这也就是我们要讲的Thread和Runnable的关系,其实它们是一样的,都是线程,最终启动线程后都会执行run()方法里面的内容,具体是怎么一回事,让我们从Thread的源码开始分析
可以看到Thread就是实现Runnable的,所以Thread也可以说是Runnable,它俩就像亲生兄弟一样。由于我们创建线程的时候第一步都是new Thread()开始的,所以看到Thread的构造函数,继续追踪之后,你会发现如果传进来一个Runnable的话,会被赋予target的成员变量中,而target就是一个Runnable。接着,调用Thread的start()方法,我们查看start()方法的源码
我们可以看到start()方法在最后是调用了本地底层的nativeCreate()方法,这个方法我们大胆的猜测,应该是执行Thread里面的run()方法,因为我们开启线程之后,线程总是会执行run()里面的内容,所以这里应该就是调用了Thread的run()方法。我们查看run()方法的源码
到这里,实际上最终被线程执行的任务是Runnable而非Thread,Thread只是对Runnable的包装。如果target不为空则执行target的run()方法,否则执行当前对象的run()方法
Runnable和Callable同样都是线程,而它们的区别可以从其源码中看出来,下面是Runnable和Callable的源码
可以发现,Callable带有一个泛型的返回值,而Runnable并没有返回值,所以使用Callable可以返回线程的结果,而Runnable不行
Future不是线程,它可以理解为管理线程的人,不过它对线程的管理方法不是很多,这点可以从Future的源码中看出来,下面是Future的源码
关说不练假把式,我们通过例子来理解,这里的线程我们都使用线程池来执行,如果对线程池不理解的,可以查看我的博客Android进阶——多线程系列之四大线程池的使用介绍
第一步:创建线程MyCallable中是实现Callable的,泛型里面填返回值的类型,而Runnable则不用
第二步:通过线程池executor提交线程,返回对应的Future< ?>对象,若有返回值则填返回值类型,英文美文若无返回值则填?号
下面我们通过打印信息来查看Future管理类的执行结果,再一次的证明:Runnable和Callable的区别
FutureTask是Future的实现类,而且不仅是Future又是Runnable,还包装了Callable,它是这两者的合体。从FutureTask的源码可以看出
源码中可以看出构造函数中需要传进去一个Callable或者是Runnable,如果传进去是个Runnable则会被Executors.callable()转换为Callable类型的任务,即FutureTask最终都是执行Callable类型的任务。继续追踪Executors.callable()
由于FutureTask实现了Runnable,因此,它既可以通过Thread包装来直接运行,也可以通过给ExecuteService来执行,并且还可以通过get()方法获取执行结果,该函数会阻塞,直到结果返回。下面通过简单的例子演示FutureTask的用法
Android进阶——多线程系列之Thread、Runnable、Callable、Future、FutureTask的更多相关文章
- Android进阶——多线程系列之异步任务AsyncTask的使用与源码分析
AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并主线程中更新UI,通过AsyncTask可以更加方便执行后台任务以及在主线程中访问UI ...
- Android进阶——多线程系列之wait、notify、sleep、join、yield、synchronized关键字、ReentrantLock锁
多线程一直是初学者最困惑的地方,每次看到一篇文章,觉得很有难度,就马上叉掉,不看了,我以前也是这样过来的.后来,我发现这样的态度不行,知难而退,永远进步不了.于是,我狠下心来看完别人的博客,尽管很难但 ...
- Android进阶——多线程系列之四大线程池的使用介绍
线程池一直是初学者最抵触的东西,由于刚开始学习做项目并不会涉及到线程池的使用,但是不去学习它,心里又好像有个石头一直沉着,一直放心不下,其实是很简单的东西,早晚都要学,不如趁现在吧.由于文章从初学者的 ...
- Android进阶——多线程系列之Semaphore、CyclicBarrier、CountDownLatch
今天向大家介绍的是多线程开发中的一些辅助类,他们的作用无非就是帮助我们让多个线程按照我们想要的执行顺序来执行.如果我们按照文字来理解Semaphore.CyclicBarrier.CountDownL ...
- Java 并发编程——Callable+Future+FutureTask
Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...
- java多线程创建-Thread,Runnable,callable和threadpool
java创建多线程的方式有许多种,这里简要做个梳理 1. 继承Thread类 继承java.lang.Thread类,创建本地多线程的类,重载run()方法,调用Thread的方法启动线程.示例代码如 ...
- Callable,Future,FutureTask
1.概念定义 2.实现例子 3.总结 1.概念定义 1.Callable Callable是一个接口,效果类似Runnable接口.实现该接口,然后,耗时操作在call()方法中执行.与Run ...
- 12 Callable & Future & FutureTask
创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就必须通过共享变量或者使用 ...
- java 并发runable,callable,future,futureTask
转载自:http://www.cnblogs.com/dolphin0520/p/3949310.html package future_call; import java.util.concurre ...
随机推荐
- Matplotlib 入门
章节 Matplotlib 安装 Matplotlib 入门 Matplotlib 基本概念 Matplotlib 图形绘制 Matplotlib 多个图形 Matplotlib 其他类型图形 Mat ...
- swoole之任务和定时器
一.代码 <?php use Swoole\Server; /** * 面向对象的形式 + task + timer */ class WebSocket { public $server; p ...
- 文本处理三剑客与shell正则表达式
文本处理三剑客 提到对于文本的处理上,除了vim这个强大的编辑器之外,还有使用命令的形式去处理你要处理的文本,而不需要手动打开文本再去编辑.这样做的好处是能够以shell命令的形式将编辑和处理文本的工 ...
- Day7 - E - Strange Way to Express Integers POJ - 2891
Elina is reading a book written by Rujia Liu, which introduces a strange way to express non-negative ...
- php 获取时间段
switch ($type){ case 'day'://当日 $end=date(,,,date(,date('Y'))); $where=' and '.$pre.'create_time> ...
- torch.nn.Conv2d()使用
API 输入:[ batch_size, channels, height_1, width_1 ] Conv2d输入参数:[ channels, output, height_2, width_2 ...
- JAVA笔记03 变量和运算符 面试题以及笔记
标识符的命名规则需要注意哪几点? 定义 就是给类,接口,方法,变量等起名字的字符序列 组成规则 英文大小写字母 数字 $和_ 注意事项 不能以数字开头 不能是java中的关键字 区分大小写 常见的命名 ...
- C# 关于AD域的操作 (首博)
前段时间(因为懒得找具体的时间了)公司说让系统可以进行对AD域的操作,包括创建用户.于是上网查资料,了解何为AD域.还不知道的这边请https://www.cnblogs.com/cnjavahome ...
- node核心 http模块
node作为服务器更多的是web服务器 1.http模块 首先:http是一个协议.里面有通信机制,状态码一大堆乱七八糟的东西.自己写猴年马月都写不出来,这个对象帮我们集成.直接用 服务器对象: ht ...
- P1047 编程团体赛
转跳点: