建立執行緒的第三種方式Callable和Future CompletionService
阿新 • • 發佈:2019-01-31
前面已經指出通過實現Runnable時,Thread類的作用就是將run()方法包裝成執行緒執行體,那麼是否可以直接把任意方法都包裝成執行緒執行體呢?Java目前不行,但其模仿者C#中是可以的.
Callabel介面可以看成是Runnable介面的增強版,只不過其執行緒執行體call()方法比run方法更加強大罷了:
>>call()方法中可以有返回值
>>call()方法中可以宣告丟擲異常.
一.建立執行緒的第三種方式----使用Callable物件進行建立
package com.amos.concurrent; import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * @ClassName: CallableAndFuture * @Description: 多執行緒中的Callable和Future學習 * @author: amosli * @email:[email protected] * @date Apr 22, 2014 12:07:26 AM*/ public class CallableAndFuture { public static void main(String[] args) throws Exception, ExecutionException { ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor(); Future<String> future = newSingleThreadExecutor.submit(new Callable<String>() {public String call() throws Exception { Thread.sleep(20); return "hi,amos"; } }); // System.out.println("future:"+future.get(1,TimeUnit.MILLISECONDS));//等待指定的時間 System.out.println("future:" + future.get()); } }
效果如下:
注:
1.這裡要注意的是,建立執行緒時執行任務不是用execute()方法去執行了,而是用submit()方法.
2.同時要注意,這裡call()方法返回值,要和上面的保持一致.
3.另外,可以設定最大等待時間,就是等待程式的返回值,這裡使用get()方法.
4.其常用的其它方法有cancel(),isCancelled(),isDone(),分別表示取消關聯的任務,是否已經取消,任務是否已經完成.
二.CompeltionService
CompeltionService主要用於提交一組Callable物件,其take方法用於返回已完成的callable任務的Future物件.可以用麥子收割來作比喻,種了10畝地的麥子,哪一塊先成熟先收割哪一塊.
舉例:
package com.amos.concurrent; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.CompletionService; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CallableAndFuture { public static void main(String[] args) throws Exception, ExecutionException { ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10); CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(newFixedThreadPool); for(int i=0;i<11;i++){//建立10個任務 final int task=i; completionService.submit(new Callable<Integer>() {//提交任務 public Integer call() throws Exception { Thread.sleep(new Random().nextInt(3000));//最多3秒 return task; } }); } //take for(int i=0;i<11;i++){ System.out.println("已完成的任務:"+completionService.take().get()); } }
效果如下圖所示:
注:由結果也可以看出來,其隨機結果是根據任務的先後完成順序來的,使用其take()方法可以獲取其返回結果.