Android之多线程解析(二)之Runnable、Callable、FutureTask

与多线程相关的方法—Callable,Future以及FutureTask

除了上文中一直分析的Runnable之外,Java中还存在Callbale,Future,FutureTask与多线程相关的概念,与Runnable不同的则是这三个方法只能用于线程池中,Runnable则可以同时在运用在Thread和线程池中。

Callable与Runnable功能相似,不同在与Callable是一个泛型接口,他有一个泛型参数V,该接口中有一个返回值(类型为V)的call()函数,而Runnable的run函数不能将结果返回到客户程序中:

public interface Callable<V>{
    //返回V类型的结果
    V call() throws Exception;
}
//为加深理解,假如Runnable的源码作为对比
public interface Runnable{
    //返回V类型的结果
    public abstract void run();
}

博客看到此处,即对Runnable以及Callable有了比较大致的了解,但是这两种机制存在着一个无法避免的缺陷,即一旦使用后就很难做到有效的控制。而Future的出现即解决了这种问题,Future为线程池制订了可管理的任务标准。Future提供了对Runnable或者Callable的任务的执行结果进行管理(取消,查询是否完成,获取结果,设置结果;分别对应着cancel,isDone,get,set函数,且get函数调用后会发生阻塞,直到执行完成返回结果)。Future声明如下:

public interface Future<V>{
    boolean cancel(boolean mayInterruptIfRunning);

    boolean isCancelled();

    boolean isDone();

    V get() throws InterruptedException,ExecutionException;

    V get(long timeout,TimeUint unit)
        throws InterruptedException,ExecutionException,TimeoutException;
}

Future只是定义了一些规范的接口,FutureTask则是具体的实现类。FutureTask实现了RunnableFuture,而RunnableFuture实现了Runnable又实现了Future这两个接口,因此FutureTask同时具有两者的能力。FutureTask代码如下:

public class FutureTask<V> implements RunnableFuture<V>{
    //代码省略
}

再看RunnabelFuture类定义:

public class RunnabelFuture<V> implements Runnable,Future<V>{
    void run();
}

FutureTask会像Thread包装Runnable那样对Runnable和Callbale进行包装,Runnbale与Callbale由构造函数注入。

public FutureTask(Callable<V> callable){
    if(callable==null) throws new NullPointerException();
    this.callable=callable;
    this.state=NEW;     // ensure visibility of callable
}

public FutureTask(Runnable runnable,V result){
    this.callable=Executors.callable(runnable,result);
    this.state=NEW;     // ensure visibility of callable
}

由上述代码即可看出,无论在构造函数中传输runnable或callable对象,都会被转换为callable对象,即可知道最终都是对Callable对象进行操作,该适配函数的实现如下:

public static <T> Callable<T> callable(Runnable task,T result){
    if(task==null) throws new NullPointerException();
    return new RunnableAdapter<T>(task,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;
    }
}

由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可提交给ExecuteService来执行。且可直接通过get()获取执行结果,该函数会一直阻塞到结果返回。因此,FutureTask既是Future,Runnable,又包装了Callable,即为两者的合体
下面通过一个Java程序简单演示Runnable,Callable,FutureTask的运用:

public class FutureDemo {

    static ExecutorService mExecutor=Executors.newSingleThreadExecutor();

    public static void main(String[] args){
        try {
            FutureWithRunnable();
            FutureWithCallable();
            FutureWithFutureTask();
        } catch (Exception e) {
            // TODO: handle exception
        }
    }

    private static void FutureWithRunnable() throws InterruptedException,ExecutionException{
        Future<?> result=mExecutor.submit(new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                fibc(20);
            }
        });
        System.out.println("Future result from Runnable : "+result.get());
    }

    private static void FutureWithCallable() throws InterruptedException,ExecutionException{
        Future<Integer> result2=mExecutor.submit(new Callable<Integer>(){

            public Integer call() throws Exception {
                // TODO Auto-generated method stub
                return fibc(20);
            }

        });
        System.out.println("Future result from Callable : "+result2.get());
    }

    private static void FutureWithFutureTask() throws InterruptedException,ExecutionException{
        FutureTask<Integer> futuretask=new FutureTask<Integer>(
                new Callable<Integer>() {
                    public Integer call() throws Exception {
                        return fibc(20);
                    }
                });
        mExecutor.submit(futuretask);
        System.out.println("Future result from FutureTask : "+futuretask.get());
    }

    private static int fibc(int num){
        if(num == 0)
            return 0;
        if(num == 1)
            return 1;
        return fibc(num-1)+fibc(num-2);
    }
}

运行结果为:
Future result from Runnable : null
Future result from Callable : 6765
Future result from FutureTask : 6765

由上述示例代码以及结果可以看出,以Runnable作为对象的执行后的结果无法通过get()函数方法获得。而使用Callable以及调用Callable的FutureTask可以通过get()函数获取执行后的结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值