上一篇對線程的基礎概念和如何使用做了些基本的介紹 本篇將繼續對線程深入的學習
多線程編程基礎之 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()**的返回值 如圖:

######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();

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