多线程编程之 Runnable、Callable、Future、FutureTask和AsyncTask源码分析

上一篇对线程的基础概念和如何使用做了些基本的介绍 本篇将继续对线程深入的学习
多线程编程基础之 wait()、notify()、sleep()、join()、yield()、synchronized关键字Lock锁等

首先了解下多线程中Runnable、Callable、Future、FutureTask
  1. Runnable和Callable都是接口 区别在于回调函数是否有返回值 单独来讲他们跟线程是一点关系都没有的(就是一个接口嘛)
public interface Runnable {
       public abstract void run();
}
public interface Callable<V> {
    V call() throws Exception;
}
  1. Future、FutureTask 其中Future是一个接口 FutureTask是其实现类 同时也实现了Runnable接口
public interface Future<V> {
   boolean cancel(boolean mayInterruptIfRunning);
   boolean isCancelled();
   boolean isDone();//
   V get() throws InterruptedException, ExecutionException;
   V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException, TimeoutException;
}
public interface RunnableFuture<V> extends Runnable, Future<V> {
   void run();
}
public class FutureTask<V> implements RunnableFuture<V> {......}
Runnable、Callable、Future、FutureTask与线程的关系

通过上面源码确实没有看出他们与线程的关系 是如何使用在线程中的呢?

  1. Runnable在线程中的使用

    new Thread(new Runnable(){run().....}).start();


    通过源码可以看出 Thread实现了Runnable接口 在成员变量target不为空的时候 执行target的run()函数 为空就执行实现接口Runnable的回调函数run()
    同时要注意的是只有Thread在调用start()函数后 run()函数才真正的在分线程中执行 否则在start()调用前执行run()函数那就不是在分线程中执行了(这是一般情况下来讲,抛开分线程中创建Thread执行Run()不说)

  2. Callable在线程中的使用:
    一般情况下Callable是无法直接在线程中使用的 需要通过FutureTask进行包装一下 上面源码也看到FutureTask是继承了RunnableFuture接口的(目的就是将其转换为Runnable传入Thread(Runnable)构造函数去分线程执行call()函数) 其作用有可以在线程中获取call()的返回值 取消异步任务 等其他相关操作

    static class Task implements Callable<Integer> {
         @Override
         public Integer call() throws Exception {
             int i=0;
             for(;i<5;i++){
                 System.out.println("线程:"+Thread.currentThread().getName()+"  i="+i);
                 Thread.sleep(500);
             }
             return i;
         }
     }
    
     public static void main(String[] args) throws Exception {
         Task task = new Task();
         FutureTask futureTask=new FutureTask<Integer>(task){
             //异步任务执行完成,回调
             @Override
             protected void done() {
                 try {
                     //get()获取异步任务返回值
                     System.out.println("Callable返回值:"+get());
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 } catch (ExecutionException e) {
                     e.printStackTrace();
                 }
             }
         };
         new Thread(futureTask).start();
         }
    
    线程:Thread-0  i=0
    

线程:Thread-0 i=1
线程:Thread-0 i=2
线程:Thread-0 i=3
线程:Thread-0 i=4
Callable返回值:5

**FutureTask**在线程执行完成后 会回调**done()** 调用**get()**函数可以在线程执行完成后获取**Callable**接口回调函数**call()**的返回值 如图:
![thread04](http://upload-images.jianshu.io/upload_images/2158254-5aaf7c2c5d121572.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

######AsyncTask源码分析 

1. 在Android中可以将耗时的操作交由**AsyncTask**去操作 上面对Runnable、Callable、Future、FutureTask做了比较详细的分析和使用 其实AsyncTask就是采用的通过FutureTask能获取Callable接口call()函数返回值的思路去实现的 

new AsyncTask<Void,Void,Void>(){
@Override
protected void onPreExecute() {
}
//分线程中执行
@Override
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}.execute();

![](http://upload-images.jianshu.io/upload_images/2158254-eda4a72d72b2d362.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

上图只是对**AsyncTask**执行流程图做了粗略的分析 其中doInBackground()函数是在Callable的call()里面执行的 并通过FutureTask包装为Runnable交由分线程去执行 再通过FutureTask的get()函数获取doInBackground()的返回值 通过InternalHandler发送消息到主线程执行AsyncTask的onPostExecute(result)函数方法
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容