經過實現Callable接口一樣可以建立一個線程,但與Runnable接口不一樣的是Callable接口有返回值。java
JDK源碼:併發
@FunctionalInterface public interface Callable<V> { V call() throws Exception; }
能夠看出,與Runnable一樣屬於一個接口方法,但二者不一樣的是,Callable接口有返回值且支持泛型。ide
Callable的使用通常是配置線程池ExecutorService來使用。其能夠經過一個submit()方法來讓一個Callable接口執行,返回一個Future。經過Future的get方法能夠得到結果。
案例:工具
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class Demo03 { public static void main(String[] args) throws InterruptedException, ExecutionException { // 建立一個線程池 ExecutorService es=Executors.newCachedThreadPool(); // 建立線程對象 MyThread mt=new MyThread(); //使用Future Future<Integer> fu=es.submit(mt); //經過get方法得到返回值 System.out.println(fu.get()); } } class MyThread implements Callable<Integer>{ @Override public Integer call() throws Exception { // TODO Auto-generated method stub Thread.sleep(1000); return 2; } }
get方法調用後會阻塞當前線程,實際使用時建議重寫get方法,使用能夠設置超時時間的重載get方法。線程
JDK源碼:code
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; }
其中cancel方法是試圖取消一個線程的執行。
cancel並不必定能取消線程的執行,由於一個任務可能已完成,已取消或者一些其它緣由,存在取消失敗的可能。
返回值boolean,當取消成功返回true,失敗返回false。
參數mayInterruptIfRunning,表示是否使用中斷的方式取消線程執行。
因此有時候,爲了讓任務有可以取消的功能,就使⽤ Callable 來代替 Runnable 。
若是爲了可取消性⽽使⽤ Future 但⼜不提供可⽤的結果,則能夠聲明 Future<?> 形式類型、並返回 null 做爲底層任務的結果。對象
JDK源碼:繼承
public interface RunnableFuture<V> extends Runnable, Future<V>
FutureTask實現了RunnableFuture接口,而RunnableFuture接口則繼承了Runnable接口與Future接口。
FutureTask類至關因而一個工具類,使用它咱們不用本身去實現Future接口中那些複雜的抽象方法。
案例:接口
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; public class Demo04 { public static void main(String[] args) throws InterruptedException, ExecutionException { // 建立線程池 ExecutorService es=Executors.newCachedThreadPool(); //建立FutureTask類 FutureTask<Integer> ft=new FutureTask<>(new Task()); //使用sumit方法 es.submit(ft); //輸出 System.out.println(ft.get()); } } class Task implements Callable<Integer>{ @Override public Integer call() throws Exception { // TODO Auto-generated method stub Thread.sleep(1000); return 3; } }
在不少⾼併發的環境下,有可能Callable和FutureTask會建立屢次。FutureTask可以在⾼併發環境下確保任務只執⾏⼀次。get