面試題:java Runnable與Callable 的區別
阿新 • • 發佈:2022-04-03
相同點
- 都是介面;(廢話,當然是介面了)
- 都可用來編寫多執行緒程式;
- 都需要呼叫Thread.start()啟動執行緒。
- Callable是類似於Runnable的介面,實現Callable介面的類和實現Runnable的類都是可被其它執行緒執行的任務。
不同點
-
實現Callable介面的任務執行緒能返回執行結果,而實現Runnable介面的任務執行緒不能返回結果,這是核心區別;
注意點:Callable介面支援返回執行結果,此時需要呼叫FutureTask.get()方法實現,此方法會阻塞主執行緒直到獲取‘將來’結果;當不呼叫此方法時,主執行緒不會阻塞! -
Callable介面的call()方法允許丟擲異常,而Runnable介面的run()方法的異常只能在內部消化,不能繼續上拋;
-
Runnable可以作為Thread構造器的引數,通過開啟新的執行緒來執行,也可以通過執行緒池來執行。而Callable只能通過執行緒池執行。
Callable實戰
下面是Callable的應用場景,用於求和並列印計算結果。
import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class SumCallableImpl implements Callable<Long> { private final long from; private final long to; SumCallableImpl(long from, long to) { this.from = from; this.to = to; } @Override public Long call() { long acc = 0; for (long i = from; i <= to; i++) { acc = acc + i; } System.out.println(Thread.currentThread().getName() + " : " + acc); return acc; } public static void main(String[] args) throws Exception { ExecutorService executor = Executors.newFixedThreadPool(3); List<Future<Long>> results = executor.invokeAll(Arrays.asList( new SumCallableImpl(0, 10), new SumCallableImpl(0, 1_000), new SumCallableImpl(0, 1_000_000) )); executor.shutdown(); System.out.println("列印執行結果:"); for (Future<Long> result : results) { System.out.println(result.get()); } } }