版權聲明:本文爲博主原創文章,未經博主容許不得轉載
源碼:github.com/AnliaLee
你們要是看到有錯誤的地方或者有啥好的建議,歡迎留言評論html
在 大話Android多線程(一) 一文中,咱們聊了建立線程的兩種方式(繼承Thread和實現Runnable接口),並比對了它們的區別。本章咱們將介紹第三種方式 —— 經過實現Callable接口來建立線程java
往期回顧
大話Android多線程(一) Thread和Runnable的聯繫和區別
大話Android多線程(二) synchronized使用解析
大話Android多線程(三) 線程間的通訊機制之Handlerandroid
咱們先簡單舉個栗子,看看經過實現Callable接口來建立線程的方式和以前兩種有什麼區別git
某日,高鐵站前,老C和他兒子作別,兒子:「爸爸,你走吧。」老C望了望路邊的小攤,說道github
說完老C便走去小攤買橘子了(實現Callable接口,重寫call()方法)編程
public static class TestCallable implements Callable{
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + ":我買幾個橘子去。你就在此地,不要走動" + " 時間:" + getTime());
Thread.sleep(2000);//模擬買橘子的時間
return Thread.currentThread().getName() + ":我買完橘子回來了" + " 時間:" + getTime();
}
}
複製代碼
兒子天然是乖乖站在原地等爸爸買橘子多線程
public class CallableTest {
//省略部分代碼...
public static void main(String args[]){
TestCallable callable = new TestCallable();
FutureTask<String> futureTask = new FutureTask<String>(callable);
Thread thread1 = new Thread(futureTask, "爸爸");
thread1.start();
System.out.println("兒子還沒收到橘子" + " 時間:" + getTime());//驗證主線程的執行狀況
try{
System.out.println(futureTask.get());
System.out.println("兒子收到橘子" + " 時間:" + getTime());//驗證主線程的執行狀況
}catch (InterruptedException | ExecutionException e){
}
}
}
複製代碼
正常買到橘子的運行結果以下併發
若是沒買到橘子呢(咱們嘗試在call()方法中拋出異常,而後在調用get()方法時進行捕獲)?app
public static class TestCallable implements Callable{
private int ticket = 10;
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + ":我買幾個橘子去。你就在此地,不要走動" + " 時間:" + getTime());
Thread.sleep(2000);//模擬買橘子的時間
System.out.println(Thread.currentThread().getName() + ":橘子賣完了" + " 時間:" + getTime());
throw new NullPointerException("橘子賣完了");
}
}
public static void main(String args[]){
TestCallable callable = new TestCallable();
FutureTask<String> futureTask = new FutureTask<String>(callable);
Thread thread1 = new Thread(futureTask, "爸爸");
thread1.start();
System.out.println("兒子站在原地" + " 時間:" + getTime());//驗證主線程的執行狀況
try{
System.out.println(futureTask.get());
System.out.println("兒子收到橘子" + " 時間:" + getTime());//驗證主線程的執行狀況
}catch (InterruptedException | ExecutionException e){
System.out.println("兒子沒收到橘子" + " 時間:" + getTime());//驗證主線程的執行狀況
}
}
複製代碼
另外須要注意的是,爸爸的錢只夠買一袋橘子(任務只能執行一次)異步
public static void main(String args[]){
TestCallable callable = new TestCallable();
FutureTask<String> futureTask = new FutureTask<String>(callable);
Thread thread1 = new Thread(futureTask, "爸爸去了第一個攤位");
Thread thread2 = new Thread(futureTask, "爸爸去了第二個攤位");
Thread thread3 = new Thread(futureTask, "爸爸去了第三個攤位");
thread1.start();
thread2.start();
thread3.start();
System.out.println("兒子站在原地" + " 時間:" + getTime());//驗證主線程的執行狀況
try{
System.out.println(futureTask.get());
System.out.println("兒子收到橘子" + " 時間:" + getTime());//驗證主線程的執行狀況
}catch (InterruptedException | ExecutionException e){
System.out.println("兒子沒收到橘子" + " 時間:" + getTime());//驗證主線程的執行狀況
}
}
複製代碼
總結上面的案例:
Future是一個接口,而FutureTask實現了RunnableFuture接口,RunnableFuture繼承了Runnable接口和Future接口(繼承關係見下圖)
FutureTask用於異步獲取執行結果或取消執行任務的場景,它的主要功能有:
- 能夠判斷任務是否完成
- 能夠獲取任務執行結果
- 能夠中斷任務
更詳細的源碼解析及用法能夠看下這幾篇博客
Java併發編程:Callable、Future和FutureTask原理解析
Java FutureTask 源碼分析 Android上的實現
FutureTask的用法及兩種經常使用的使用場景
區別於實現Runnable接口建立線程的方式,以上這兩點功能Runnable就沒法實現了
在UI線程中使用時(尤爲是後續還有更新UI的操做)要特別注意這點,以避免形成界面卡頓。那麼要如何處理這種多線程執行耗時任務,等待結果,而後再更新UI的狀況呢?沒錯!就是使用咱們上一章講到的Handler,Android系統提供的AsyncTask也正是用到了這一方式實現了異步操做,咱們將在後續的章節詳細介紹AsyncTask
此外,除了直接new一個Thread,咱們還能夠利用線程池結合Callable執行多線程任務
public static void main(String args[]){
TestCallable callable = new TestCallable();
ExecutorService executor = Executors.newCachedThreadPool();
Future<String> future = executor.submit(callable);
//或者
//FutureTask<String> future = new FutureTask<String>(callable);
//executor.execute(future);
System.out.println("兒子站在原地" + " 時間:" + getTime());//驗證主線程的執行狀況
try{
System.out.println(future.get());
System.out.println("兒子收到橘子" + " 時間:" + getTime());//驗證主線程的執行狀況
}catch (InterruptedException | ExecutionException e){
System.out.println("兒子沒收到橘子" + " 時間:" + getTime());//驗證主線程的執行狀況
}
}
複製代碼
那麼線程池又是啥?留到下一章咱們再「大話」一番吧
本篇博客到此結束,若你們有啥疑問或建議歡迎留言評論,感激涕零。若是以爲寫得還不錯麻煩點個贊,大家的支持是我最大的動力~