Java併發編程實踐之Callable,Future,RutureTask的使用

一般使用線程有兩種方式:繼承Thread類重寫run方法;另一種就是實現Runnable接口,實現run方法。但是run方法沒有返回值,假如我們在使用線程的時候想要知道運行結果,就只能使用重寫run方法,並且使用回調來得到運行結果。但是我們Callable接口的call方法,可以返回執行結果。如下:

public interface Runnable
{

    public abstract void run();
}
public interface Callable
{

    public abstract Object call()
        throws Exception;
}
Future 表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。計算完成後只能使用 get 方法來獲取結果,如有必要,計算完成前可以阻塞此方法。取消則由 cancel 方法來執行。還提供了其他方法,以確定任務是正常完成還是被取消了。一旦計算完成,就不能再取消計算。如果爲了可取消性而使用 Future 但又不提供可用的結果,則可以聲明 Future<?> 形式類型、並返回 null 作爲底層任務的結果。

 public abstract boolean <code><strong><a target=_blank href="">cancel</a></strong>(boolean mayInterruptIfRunning)</code> ;
cancel用來取消任務,取消成功返回true,取消失敗返回false。mayInterruptIfRunning表示正在執行但還沒執行完的任務是否可以取消。如果任務已完成、或已取消。那麼不管mayInterruptIfRunning是ture還是false,方法執行返回false。如果任務在執行中,那麼若mayInterruptIfRunning爲ture那麼返回true;若mayInterruptIfRunning爲false,結果返回false。如果任務還沒執行,不管mayInterruptIfRunning是ture還是false,方法返回true。

 public abstract Object get()
        throws InterruptedException, ExecutionException;
get方法用來獲取線程執行返回結果。這個方法回阻塞,知道返回結果。
   public abstract boolean isCancelled();
 如果在任務正常完成前將其取消,則返回 true。
get(long timeout, TimeUnit unit) 
  如有必要,最多等待爲使計算完成所給定的時間之後,獲取其結果(如果結果可用)。
public abstract boolean isDone();
  如果任務已完成,則返回 true

FutureTask:可取消的異步計算。利用開始和取消計算的方法、查詢計算是否完成的方法和獲取計算結果的方法,此類提供了對 Future 的基本實現。僅在計算完成時才能獲取結果;如果計算尚未完成,則阻塞 get 方法。一旦計算完成,就不能再重新開始或取消計算。 
Callable:Callable 接口類似於 Runnable,兩者都是爲那些其實例可能被另一個線程執行的類設計的。但是 Runnable 不會返回結果,並且無法拋出經過檢查的異常。 Callable 接口只有一個call方法,如下:

    public abstract Object call()
        throws Exception;
因爲Executor接口只提供了一個方法,參數中只能接受Runnable類型,如下:

    public abstract void execute(Runnable runnable);
因此,Callable只能與ExecutorService一起使用。因爲ExecutorService提供了可接受Callable類型的參數。如下:
   public abstract Future submit(Callable callable);

    public abstract Future submit(Runnable runnable, Object obj);

    public abstract Future submit(Runnable runnable);

下面來看使用示例:
示例1:使用Callable和Future,並且輸出線程計算返回值

public class Test3 {
	
	public static void main(String[] args) {
		
		ExecutorService executor=Executors.newCachedThreadPool();
		
		Future<Integer> future=executor.submit(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				int sum=0;
				for (int i = 1; i <= 1000; i++) {
					sum+=i;
				}
				
				return sum;
			}
		});
		
		try {
			System.out.println("線程執行結果:"+future.get());
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
輸出結果:

線程執行結果:500500

示例2:使用Callable和FutureTask,並且輸出線程計算返回值

public class CallableFutureTask {
	
	public static void main(String[] args) {
		
		ExecutorService executor=Executors.newCachedThreadPool();
		
		FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				int sum=0;
				for (int i = 1; i <= 1000; i++) {
					sum+=i;
				}
				
				return sum;
			}
		});
		
		executor.submit(futureTask);
		
		executor.shutdown();
		
		try {
			System.out.println("線程執行結果:"+futureTask.get());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
示例3:使用使用Callable和FutureTask,並且輸出線程計算返回值。用啓動普通線程來執行
public class CallableFutureTaskThread {
	
	public static void main(String[] args) {
		
		FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
			@Override
			public Integer call() throws Exception {
				int sum=0;
				for (int i = 1; i <= 1000; i++) {
					sum+=i;
				}
				
				return sum;
			}
		});
		
		Thread thread=new Thread(futureTask);
		thread.start();
		
		try {
			System.out.println("線程執行結果:"+futureTask.get());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章