上一篇对线程的基础概念和如何使用做了些基本的介绍 本篇将继续对线程深入的学习
多线程编程基础之 wait()、notify()、sleep()、join()、yield()、synchronized关键字Lock锁等
首先了解下多线程中Runnable、Callable、Future、FutureTask
- Runnable和Callable都是接口 区别在于回调函数是否有返回值 单独来讲他们跟线程是一点关系都没有的(就是一个接口嘛)
public interface Runnable {
public abstract void run();
}
public interface Callable<V> {
V call() throws Exception;
}
- 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与线程的关系
通过上面源码确实没有看出他们与线程的关系 是如何使用在线程中的呢?
-
Runnable在线程中的使用
new Thread(new Runnable(){run().....}).start();
通过源码可以看出 Thread实现了Runnable接口 在成员变量target不为空的时候 执行target的run()函数 为空就执行实现接口Runnable的回调函数run()
同时要注意的是只有Thread在调用start()函数后 run()函数才真正的在分线程中执行 否则在start()调用前执行run()函数那就不是在分线程中执行了(这是一般情况下来讲,抛开分线程中创建Thread执行Run()不说) -
Callable在线程中的使用:
一般情况下Callable是无法直接在线程中使用的 需要通过FutureTask进行包装一下 上面源码也看到FutureTask是继承了Runnable、 Future接口的(目的就是将其转换为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)函数方法
网友评论