Callable,Future,FutrueTask,CompletionService 詳解

package com.dy.pool;


import java.util.concurrent.*;

/**
 * 1: Callable<V> 返回結果而且可能拋出異常的任務。實現者定義了一個不帶任何參數的叫作 call 的方法。

      Callable 接口相似於 Runnable,二者都是爲那些其實例可能被另外一個線程執行的類設計的。

      可是 Runnable 不會返回結果,而且沒法拋出通過檢查的異常。


 2:  Future<V> 表示異步計算的結果
     Future 表示異步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。

 3:  CompletionService<V> 將生產新的異步任務與使用已完成任務的結果分離開來的服務 ,

 *   生產者 submit 執行的任務。使用者 take 已完成的任務,並按照完成這些任務的順序處理它們的結果。
 *
 *
 *   4:FutureTask<V> 可取消的異步計算。實現了RunbaleFuture,
 *
 *   RunbaleFuture 繼承了Future和Runbale,因此FutureTask<V>能夠當作一個線程去提交或執行。
 *
 *   返回FutureTask的操做也能夠用Future來接受
 *
 *    利用開始和取消計算的方法、查詢計算是否完成的方法和獲取計算結果的方法,此類提供了對 Future 的基本實現。
 *
 *    僅在計算完成時才能獲取結果;若是計算還沒有完成,則阻塞 get 方法。一旦計算完成,就不能再從新開始或取消計算。

     可以使用 FutureTask 包裝 Callable 或 Runnable 對象。由於 FutureTask 實現了 Runnable,

      因此可將 FutureTask 提交給 Executor 執行。
 *
 * @author dengyang
 *
 * @2012-4-13下午12:57:57
 */
public class CallableAndFuture {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		/**
		 * Future使用
		 */
		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		
		 Future<String> future = threadPool.submit(new Callable<String>(){
			public String call() throws Exception {
				Thread.sleep(1000);
				return "I am dengyang";
			}
		});

		System.out.println("我先去作其餘事情了...");
		 try {
			System.out.println("The Callable return :"+future.get());
//			System.out.println("The Callable return :"+future.get(100,TimeUnit.SECONDS));
		}  catch (Exception e) {
			e.printStackTrace();
		 }
		threadPool.shutdown();

		/**
		 * FutureTask使用
                */
		ExecutorService executor = Executors.newFixedThreadPool(3);
		FutureTask<String> futureTask =
				new FutureTask<String>(new Callable<String>() {
					public String call() {
						return "我執行完了";
					}});
//		executor.submit(futureTask);
		executor.execute(futureTask);
		System.out.println("線程在執行FutureTask,我先去處理別的事情了");
		try {
			System.out.println("futureTask return:"+futureTask.get());
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}
		executor.shutdown();
		 /*
		    CompletionService使用
		  * 有多個線程,哪一個先返回數據,就先獲取哪一個
		  */
		 ExecutorService threadPool2 = Executors.newFixedThreadPool(10);
		 CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(threadPool2);
		 for(int i=0;i<10;i++){
			 final int seq = i;
			 completionService.submit(new Callable<Integer>(){
					public Integer call() throws Exception {
						return seq;
					}
				});
		 }
		System.out.println("多線程執行任務時,我先去作其餘事情了...");
		 try {
			 System.out.println("the first result of The Callable return :"+completionService.take().get());
			 for(int i=0;i<10;i++){
				 System.out.println(" The Callable return :"+completionService.take().get());
			 }
		}  catch (Exception e) {
			e.printStackTrace();
		}
		 threadPool2.shutdown();
	}
}


使用Callable,Future返回結果 
Future<V>表明一個異步執行的操做,經過get()方法能夠得到操做的結果,若是異步操做尚未完成,則,get()會使當 前線程阻塞。FutureTask<V>實現了Future<V>和Runable<V>。Callable表明一 個有返回值得操做。 java

ExecutoreService提供了submit()方法,傳遞一個Callable,或Runnable,返回Future。若是Executor後臺線程池尚未完成Callable的計算,這調用返回Future對象的get()方法,會阻塞直到計算完成。  數組

FutureTask使用過程當中,咱們一般能夠迭代FutureTask的數組,若是任務尚未完成則當前線程會阻塞, 多線程

若是咱們希 望任意字任務完成後就把其結果加到result中,而不用依次等待每一個任務完成,可使CompletionService。 異步

生產者submit()執行 的任務。使用者take()已完成的任務,並按照完成這些任務的順序處理它們的結果 。 spa

也就是調用CompletionService的take方法是,會返回按完成順序放回任務的結果, 線程

CompletionService內部維護了一個 阻塞隊列BlockingQueue,若是沒有任務完成,take()方法也會阻塞。  設計


類模型: code

相關文章
相關標籤/搜索