使用解析
1、首先查看官方文檔和源碼是如何講解的
可以知道以下幾點:
1、Callable接口類似於Runnable接口
2、Callable有返回值
3、Callable可以拋出異常
4、調用call()方法
5、Callable支持泛型
2、既然和Runnable接口類似,就直接創建一下
class MyThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("call()"); return "123"; } }
3、重點:如何啟動呢?
要知道線程的啟動只能通過 new Thread().start()
那該怎么辦?
現在知道的是Thread類,和Runnable接口有關系,我們是否可以通過Runnable接口和Thread類掛上關系呢?
通過圖解拆分關系
-
現在你是Callable接口,Runnable接口是的女朋友,Thread類是你女朋友的閨蜜
-
而現在你想認識你女朋友的閨蜜,怎么辦呢?
-
如果你直接去找你女朋友的閨蜜,肯定會有些突兀或者造成誤會!
-
肯定需要通過你女朋友的介紹,對吧!
-
那么你的女朋友要如何介紹呢?這是一個問題!
4、查看Runnable接口在文檔中的說明
Runnable接口本身沒有說明好看的,只是一個函數式接口,里面有個run()
方法,僅此而已!
但是它有兩個重要的實現類,圖中已經標出:
往下翻,在構造器中你會發現可以丟入一個Callable接口
那么現在就可以通過FutureTask實現類和Thread類掛上關系了!
具體使用
有兩個坑,需要注意返回參數和緩存
創建Callable線程並啟動
package com.zxh.callable; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class CallableTest { public static void main(String[] args) { MyThread myThread = new MyThread(); FutureTask futureTask = new FutureTask(myThread); // 適配器類 new Thread(futureTask).start(); } } class MyThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("call()"); return "123"; } }
Callable返回的參數和注意點
獲取返回的參數
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableTest { public static void main(String[] args) throws ExecutionException, InterruptedException { MyThread myThread = new MyThread(); FutureTask futureTask = new FutureTask(myThread); // 適配器類 new Thread(futureTask).start(); Object o = futureTask.get(); System.out.println(o); } } class MyThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("call()"); return "123"; } }
注意點
futureTask.get()
方法可能會阻塞
因為call()
中可能會存在耗時的任務,所以在獲取返回值的時候,就會等待(阻塞)。
-
當你使用兩個線程調用的時候,會發現輸出只有1次。
-
因為結果被緩存,提高了效率
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; public class CallableTest { public static void main(String[] args) throws ExecutionException, InterruptedException { MyThread myThread = new MyThread(); FutureTask futureTask = new FutureTask(myThread); // 適配器類 new Thread(futureTask, "A").start(); new Thread(futureTask, "B").start(); //結果會被緩存 Object o = futureTask.get(); // 會阻塞,一般通過異步操作 System.out.println(o); } } class MyThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("call()"); return "123"; } }