上一篇對線程的基礎(chǔ)概念和如何使用做了些基本的介紹 本篇將繼續(xù)對線程深入的學(xué)習(xí)
多線程編程基礎(chǔ)之 wait()、notify()、sleep()、join()、yield()、synchronized關(guān)鍵字Lock鎖等
首先了解下多線程中Runnable、Callable、Future、FutureTask
- Runnable和Callable都是接口 區(qū)別在于回調(diào)函數(shù)是否有返回值 單獨(dú)來講他們跟線程是一點(diǎn)關(guān)系都沒有的(就是一個接口嘛)
public interface Runnable {
public abstract void run();
}
public interface Callable<V> {
V call() throws Exception;
}
- Future、FutureTask 其中Future是一個接口 FutureTask是其實(shí)現(xiàn)類 同時也實(shí)現(xiàn)了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與線程的關(guān)系
通過上面源碼確實(shí)沒有看出他們與線程的關(guān)系 是如何使用在線程中的呢?
-
Runnable在線程中的使用
new Thread(new Runnable(){run().....}).start();
通過源碼可以看出 Thread實(shí)現(xiàn)了Runnable接口 在成員變量target不為空的時候 執(zhí)行target的run()函數(shù) 為空就執(zhí)行實(shí)現(xiàn)接口Runnable的回調(diào)函數(shù)run()
同時要注意的是只有Thread在調(diào)用start()函數(shù)后 run()函數(shù)才真正的在分線程中執(zhí)行 否則在start()調(diào)用前執(zhí)行run()函數(shù)那就不是在分線程中執(zhí)行了(這是一般情況下來講,拋開分線程中創(chuàng)建Thread執(zhí)行Run()不說) -
Callable在線程中的使用:
一般情況下Callable是無法直接在線程中使用的 需要通過FutureTask進(jìn)行包裝一下 上面源碼也看到FutureTask是繼承了Runnable、 Future接口的(目的就是將其轉(zhuǎn)換為Runnable傳入Thread(Runnable)構(gòu)造函數(shù)去分線程執(zhí)行call()函數(shù)) 其作用有可以在線程中獲取call()的返回值 取消異步任務(wù) 等其他相關(guān)操作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){ //異步任務(wù)執(zhí)行完成,回調(diào) @Override protected void done() { try { //get()獲取異步任務(wù)返回值 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**在線程執(zhí)行完成后 會回調(diào)**done()** 調(diào)用**get()**函數(shù)可以在線程執(zhí)行完成后獲取**Callable**接口回調(diào)函數(shù)**call()**的返回值 如圖:

######AsyncTask源碼分析
1. 在Android中可以將耗時的操作交由**AsyncTask**去操作 上面對Runnable、Callable、Future、FutureTask做了比較詳細(xì)的分析和使用 其實(shí)AsyncTask就是采用的通過FutureTask能獲取Callable接口call()函數(shù)返回值的思路去實(shí)現(xiàn)的
new AsyncTask<Void,Void,Void>(){
@Override
protected void onPreExecute() {
}
//分線程中執(zhí)行
@Override
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}.execute();

上圖只是對**AsyncTask**執(zhí)行流程圖做了粗略的分析 其中doInBackground()函數(shù)是在Callable的call()里面執(zhí)行的 并通過FutureTask包裝為Runnable交由分線程去執(zhí)行 再通過FutureTask的get()函數(shù)獲取doInBackground()的返回值 通過InternalHandler發(fā)送消息到主線程執(zhí)行AsyncTask的onPostExecute(result)函數(shù)方法
