源码探索系列15---那个AsyncTask里面的FutureTask
来源:互联网 发布:爱钱进可靠吗 知乎 编辑:程序博客网 时间:2024/06/06 01:31
很久前在写源码探索系类2–AsyncTask时候有提及到这个类,现在在这里把FutureTask
,Future
和Callback
,这三个火枪手的关系温习下
起航
就让我们进入主题,开始说说这个FutureTask吧。
在安装开发过程中,系统限制我们对于耗时的任务是不能执行在主线程的,必须单独开一个线程去做。
所以我们在开发过程的一种写法是下面这样
1. 用Runnable
new Thread(new Runnable() { @Override public void run() { //do something ... myHandler.sendMessage(msg); } }).run();
但有时候我们需要这个线程的运算结果,可我们没办法直接获取,因此安卓配套了一个Handler给我们用,利用他发送消息会我们的主线程,执行一些更新任务等。
2.用Callable
除了使用Runnable,我们还可以使用Callable,示例如下
ExecutorService executor = Executors.newCachedThreadPool();Future future= executor.submit(new MyCallableTask());System.out.println(" result=" + future3.get());class MyCallableTask implements Callable<String> { @Override public String call() throws Exception { return "call-result"; }}
我们的Callable和Runnable的一点区别是可以有返回值了,而且能抛出异常。
不过他只能用ExecutorService来执行,不能用在新线程中new Thread(Runnable r)
但获得他的返回值,好像不是很方便。而且这个get操作是堵塞线程的,例如改成下面这样
System.out.println("before" + System.currentTimeMillis());System.out.println(" result=" + future3.get());System.out.println("after" + System.currentTimeMillis());
打印的结果是:
before1451383552900result=call-resultafter1451383555900
时间刚好差了3秒钟。
很显然,有时候我们需要异步的,希望等运行结束了通知下我,我去获取结果,然后做点什么,改怎办呢?如果不用AsyncTask
,Thread+Handler
的方式?看下这个FutureTask
能不能帮我们点什么
FutureTask
我们先看下示例代码:
ExecutorService executor = Executors.newCachedThreadPool();MyFutureTask futureTask = new MyFutureTask(new MyCallableTask());executor.submit(futureTask);class MyCallableTask implements Callable<String> { @Override public String call() throws Exception { Thread.sleep(3000); return "call-result"; } }class MyFutureTask extends FutureTask<String> { public MyFutureTask(Callable<String> callable) { super(callable); } @Override protected void done() { try { System.out.println("执行完毕,结果是:"+get()); } catch (Exception e) { e.printStackTrace(); } }}
我们的done()
函数会被调用,当这个任务结束返回结果的话。
小小问题来了,为何这个FutureTask可以被Executor执行?我们看下他的构造
public class FutureTask<V> implements RunnableFuture<V> public interface RunnableFuture<V> extends Runnable, Future<V>
他实现了Runnable
和Future
,是个混血儿!混血儿!混血儿!Amazing
就像是AsyncTask封装好了,帮我们解脱这些繁琐的事情一样,有用!
既然这样,我们去看下他的内部的run
方法吧
public void run() { try { Callable<V> c = callable; if (c != null && state == NEW) { V result; boolean ran; try { result = c.call(); ran = true; } catch (Throwable ex) { result = null; ran = false; setException(ex); } if (ran) set(result); } } finally { ... }}
他会去调用我们的callable.call()函数,然后把结果扔给Set()
函数,如果一切正常的话。
我们看下set里面的
protected void set(V v) { if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) { outcome = v; U.putOrderedInt(this, STATE, NORMAL); // final state finishCompletion(); }}
最后调用的是finishComPletion()
private void finishCompletion() { // assert state > COMPLETING; .... done(); callable = null; // to reduce footprint}
我们看到他调用了done
函数了,而且最后把callbale给 清清清清清清清了,因为我们拿到结果了。
这个done()
函数里面什么也没有,主要是通知我们计算完毕,我们可以在这个时候去调用get()
函数去获取结果了。
说到这,想提下,知道为何AsyncTask
不能够执行两次吗?和这个FutureTask有关系吗?
后记
这次没有后记的内容。
- 源码探索系列15---那个AsyncTask里面的FutureTask
- 源码探索系列2---深入解析AsyncTask
- 源码探索系列16---初篇结尾---那个被RecyclerView替代的Listview
- java里面的FutureTask简单使用(配合源码讲解)
- android 源码探索--AsyncTask
- AsyncTask源码探索
- android之Futuretask、Timer、AsyncTask的使用及原理解析
- Asynctask源码级解析,深度探索源码之旅
- 源码探索系列8---IntentService
- 源码探索系列1---Handler与HandlerLeak的那些事
- 源码探索系列10---替代Listview的RecycleView
- 源码探索系列11---关于View的绘制
- 源码探索系列13---Window的PhoneWindow与WindowManager
- AsyncTask源码的理解
- dll里面的那个入口函数
- AsyncTask与FutureTask运用介绍
- 面试系列之AsyncTask源码深入解读
- android的asynctask里面使用toast
- 连接MySQL数据库时常见故障问题的分析与解决
- mycncart使用教程 - 修改管理员操作权限
- HDU 1010 Tempter of the Bone
- SQL总结.1
- 神奇的_scala
- 源码探索系列15---那个AsyncTask里面的FutureTask
- iOS同步对象性能对比(iOS锁性能对比)
- nginx基于cookie粘滞做的负载均衡
- [每天程序猿] 如何成为顶级技术巨匠?
- tinyos学习笔记8--TestLinkLocal例程代码说明
- mysql user权限表
- 生产者消费者模式浅析
- mycncart如何开启短信验证接口功能
- 汉字编码问题(转)