天天看點

Callable、Future和FutureTask (五)

Callable、Future和FutureTask

  • 通常大家都知道建立線程的方式主要是繼承Thread和實作Runable接口,下面為大家介紹第三種方式,實作Callable接口。Callable可以在ExecutorService的線程池中跑,并有傳回結果;也可以通過傳回的FutureTask通過new Thread的方法啟動。兩種方法通過Future的擷取執行狀态(Future 本身也是一種設計模式,它是用來取得異步任務的結果)。

結構圖

Callable、Future和FutureTask (五)

上圖可以發現,FutureTask類是Future 的一個實作,并實作了Runnable。由FutureTask的構造方法,通過futureTask的run方法,啟動callable的call方法。如果在主線程中需要執行比較耗時的操作時,但又不想阻塞主線程時,可以把這些作業交給Future對象在背景完成,當主線程将來需要時,就可以通過Future對象獲得背景作業的計算結果或者執行狀态。

常用的方法介紹:
  • isDone,結束,正常還是異常結束,或者自己取消,傳回true;
  • isCancelled 任務完成前被取消,傳回true;
  • cancel(boolean):

    1、任務還沒開始,傳回false

    2、任務已經啟動,cancel(true),中斷正在運作的任務,中斷成功,傳回true,cancel(false),不會去中斷已經運作的任務

    3、任務已經結束,傳回false

執行個體

public class UseFuture {
	
	/*實作Callable接口,允許有傳回值*/
	private static class UseCallable implements Callable<Integer>{
		private int sum;
		@Override
		public Integer call() throws Exception {
			System.out.println("Callable子線程開始計算");
			Thread.sleep(2000);
			for(int i=0;i<5000;i++) {
				sum = sum+i;
			}
			System.out.println("Callable子線程計算完成,結果="+sum);
			return sum;
		}

	}
	
	public static void main(String[] args) 
			throws InterruptedException, ExecutionException {
		
		UseCallable useCallable = new UseCallable();
		FutureTask<Integer> futureTask = new FutureTask<Integer>(useCallable);
		new Thread(futureTask).start();
		Random r = new Random();
		SleepTools.second(1);
		if(r.nextBoolean()) {//随機決定是獲得結果還是終止任務
			System.out.println("Get UseCallable result = "+futureTask.get());
		}else {
			System.out.println("中斷計算");
			futureTask.cancel(true);
		}
	}

}

           

上面隻介紹了通過newThread()的方式啟動Callable,也可以通過線程池ExecutorService來啟動線程。想知道底層實作就多看看源碼學習,這裡就不過多說明

繼續閱讀