多线程一直是初学者最抵触的东西,如果你想进阶的话,那必须闯过这道难关,特别是多线程中Thread、Runnable、Callable、Future、FutureTask这几个类往往是初学者容易搞混的。这里先总结这几个类特点和区别,让大家带着模糊印象来学习这篇文章

  1. Thread、Runnable、Callable:都是线程
  2. Thread特点:提供了线程等待、线程睡眠、线程礼让等操作
  3. Runnable和Callable特点:都是接口,并提供对应的实现方法
  4. Runnable、Callable区别:Runnable无返回值,Callable有返回值
  5. Future:提供了对Runnable和Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果等操作
  6. 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的更多相关文章

  1. Android进阶——多线程系列之异步任务AsyncTask的使用与源码分析

    AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并主线程中更新UI,通过AsyncTask可以更加方便执行后台任务以及在主线程中访问UI ...

  2. Android进阶——多线程系列之wait、notify、sleep、join、yield、synchronized关键字、ReentrantLock锁

    多线程一直是初学者最困惑的地方,每次看到一篇文章,觉得很有难度,就马上叉掉,不看了,我以前也是这样过来的.后来,我发现这样的态度不行,知难而退,永远进步不了.于是,我狠下心来看完别人的博客,尽管很难但 ...

  3. Android进阶——多线程系列之四大线程池的使用介绍

    线程池一直是初学者最抵触的东西,由于刚开始学习做项目并不会涉及到线程池的使用,但是不去学习它,心里又好像有个石头一直沉着,一直放心不下,其实是很简单的东西,早晚都要学,不如趁现在吧.由于文章从初学者的 ...

  4. Android进阶——多线程系列之Semaphore、CyclicBarrier、CountDownLatch

    今天向大家介绍的是多线程开发中的一些辅助类,他们的作用无非就是帮助我们让多个线程按照我们想要的执行顺序来执行.如果我们按照文字来理解Semaphore.CyclicBarrier.CountDownL ...

  5. Java 并发编程——Callable+Future+FutureTask

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  6. java多线程创建-Thread,Runnable,callable和threadpool

    java创建多线程的方式有许多种,这里简要做个梳理 1. 继承Thread类 继承java.lang.Thread类,创建本地多线程的类,重载run()方法,调用Thread的方法启动线程.示例代码如 ...

  7. Callable,Future,FutureTask

    1.概念定义 2.实现例子 3.总结   1.概念定义   1.Callable Callable是一个接口,效果类似Runnable接口.实现该接口,然后,耗时操作在call()方法中执行.与Run ...

  8. 12 Callable & Future & FutureTask

    创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就必须通过共享变量或者使用 ...

  9. java 并发runable,callable,future,futureTask

    转载自:http://www.cnblogs.com/dolphin0520/p/3949310.html package future_call; import java.util.concurre ...

随机推荐

  1. NodeJs koa2实现文件上传

    [转载自:]https://www.jianshu.com/p/34d0e1a5ac70 知识讲解 koa2框架是一个基于中间件的框架,也就是说,需要使用到的功能,比如路由(koa-router),日 ...

  2. LeetCode242 有效的字母异位词(Java字符数组排序&自定义排序记录)

    题目: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词.   示例 1: 输入: s = "anagram", t = "nagaram& ...

  3. Kubernetes Dashboard 【转】

    前面章节 Kubernetes 所有的操作我们都是通过命令行工具 kubectl 完成的.为了提供更丰富的用户体验,Kubernetes 还开发了一个基于 Web 的 Dashboard,用户可以用 ...

  4. Python最新暴力破解WiFi,攻破所有密码限制,最强破解!

    暴力破解wifi密码 这个代码也是非常简单,这里需要用Python中的pywifi这个库,所以需要在DOS命令下安装这个库,同样使用pip install pywifi,很简单就安装成功了,我用的是P ...

  5. 066、Java面向对象之以分步的方式实例化对象

    01.代码如下: package TIANPAN; class Book { // 定义一个新的类 String title; // 书的名字 double price; // 书的价格 public ...

  6. 树莓派 Raspberry 软件源更改 看门狗启用

    看门狗无法在pi1上执行,似乎后更高级的pi上面才可用 1.替换脚本 下面脚本请直接复制到终端执行!! 适用于raspbian-stretch(基于Debian9) sudo -s echo -e & ...

  7. 吴裕雄--天生自然java开发常用类库学习笔记:属性类Properties

    import java.util.Properties; public class PropertiesDemo01{ public static void main(String args[]){ ...

  8. C# Winform使用线程,委托定时更新界面UI控件,解决界面卡顿问题(转载)

    一.定时执行主界面控件值 1.利用定时器 Thread t = null; private void InitTSJK() { t = new Thread(new ThreadStart(GetDa ...

  9. P1037 在霍格沃茨找零钱

    转跳点:

  10. Java多线程之Java内存模型

    如果要了解Java内存模型,就得对多线程的三大特性有初步的了解. 1.原子性:独一无二.一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行.比如i = i+1:其中就包 ...