1. 程式人生 > 其它 >面試題:java Runnable與Callable 的區別

面試題:java Runnable與Callable 的區別

相同點

  1. 都是介面;(廢話,當然是介面了)
  2. 都可用來編寫多執行緒程式;
  3. 都需要呼叫Thread.start()啟動執行緒。
  4. Callable是類似於Runnable的介面,實現Callable介面的類和實現Runnable的類都是可被其它執行緒執行的任務。

不同點

  1. 實現Callable介面的任務執行緒能返回執行結果,而實現Runnable介面的任務執行緒不能返回結果,這是核心區別
    注意點:Callable介面支援返回執行結果,此時需要呼叫FutureTask.get()方法實現,此方法會阻塞主執行緒直到獲取‘將來’結果;當不呼叫此方法時,主執行緒不會阻塞!

  2. Callable介面的call()方法允許丟擲異常,而Runnable介面的run()方法的異常只能在內部消化,不能繼續上拋;

  3. 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());
       }
   }
}