美文网首页多线程Android知识Android开发
多线程编程之 Runnable、Callable、Future、

多线程编程之 Runnable、Callable、Future、

作者: 明朗__ | 来源:发表于2017-04-16 15:04 被阅读343次

上一篇对线程的基础概念和如何使用做了些基本的介绍 本篇将继续对线程深入的学习
多线程编程基础之 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](https://img.haomeiwen.com/i2158254/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();

![](https://img.haomeiwen.com/i2158254/eda4a72d72b2d362.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

上图只是对**AsyncTask**执行流程图做了粗略的分析 其中doInBackground()函数是在Callable的call()里面执行的 并通过FutureTask包装为Runnable交由分线程去执行 再通过FutureTask的get()函数获取doInBackground()的返回值 通过InternalHandler发送消息到主线程执行AsyncTask的onPostExecute(result)函数方法

相关文章

网友评论

    本文标题:多线程编程之 Runnable、Callable、Future、

    本文链接:https://www.haomeiwen.com/subject/ooyaattx.html