- 引入 Callable + Future
- Callable + Future實例
引入 Callable + Future
Executor框架的優(yōu)勢之一就是仰税,可以運行并發(fā)任務(wù)并且返回結(jié)果室琢。
我們知道Runnable對象是沒有返回值的,所以自然利用Runnable對象就無法返回結(jié)果绣的,于是就定義了一個新的接口,可以理解為是“帶有返回值的Runnable對象”欲账。
這個接口就是
Callable接口:這個接口聲明了一個call方法屡江,類似于Runnable接口的run方法,是任務(wù)具體的邏輯赛不,不同就在于可以有返回值盼理,而且這個接口是一個泛型接口,這就意味著必須聲明call方法的返回類型俄删。
我們?nèi)蝿?wù)交給線程執(zhí)行之后宏怔,什么時候執(zhí)行結(jié)束奏路,將結(jié)果返回這個時間往往是無法具體確定的,所以為了接受這個來自未來某個時刻執(zhí)行完之后的返回結(jié)果臊诊,又新增了一個Future接口:
Future接口:這個接口聲明了一些方法獲取由callable對象產(chǎn)生的結(jié)果鸽粉,并管理他們的狀態(tài)。
Callable + Future實例
接下來抓艳,我們編寫一個實例來接受任務(wù)的返回結(jié)果
實現(xiàn)一個Callable對象触机,由于返回值是Integer,所以定義為Callable<Integer>
package CreateExecutorCallableFuture;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
public class FactorialCaculator implements Callable<Integer> {
private Integer number;
public FactorialCaculator(Integer number) {
super();
this.number = number;
}
@Override
public Integer call() throws Exception {
int result = 1;
if((number == 0) || (number == 1))
return 1;
else {
for(int i=2;i<=number;i++) {
result *= i;
TimeUnit.MILLISECONDS.sleep(20);
}
}
System.out.printf("%s : %d\n",Thread.currentThread().getName(),result);
return result;
}
}
Main類創(chuàng)建一個線程池來執(zhí)行這些任務(wù)玷或,并在任務(wù)執(zhí)行完之后輸出結(jié)果
package CreateExecutorCallableFuture;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws InterruptedException {
ThreadPoolExecutor executor = (ThreadPoolExecutor)Executors.newFixedThreadPool(2);
List<Future<Integer>> resList = new ArrayList<>();
Random random = new Random();
for(int i=0;i<10;i++) {
Integer number = random.nextInt(10);
FactorialCaculator caculator = new FactorialCaculator(number);
Future<Integer> res = executor.submit(caculator);
resList.add(res);
}
do {
System.out.println("Main : Number of CompleteTasks : " + executor.getCompletedTaskCount());
for(int i=0;i<resList.size();i++) {
Future<Integer> res = resList.get(i);
System.out.printf("Main : task %d : %s\n", i, res.isDone());
}
TimeUnit.MILLISECONDS.sleep(50);
}while(executor.getCompletedTaskCount() < resList.size());
for(int i=0;i<resList.size();i++) {
Future<Integer> res = resList.get(i);
Integer number = null;
try {
number = res.get();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.printf("Main : Task %d : %s\n",i,number);
}
}
}
運行結(jié)果
Main : Number of CompleteTasks : 0
Main : task 0 : false
Main : task 1 : false
Main : task 2 : false
Main : task 3 : false
Main : task 4 : false
Main : task 5 : false
Main : task 6 : false
Main : task 7 : false
Main : task 8 : false
Main : task 9 : false
pool-1-thread-1 : 24
pool-1-thread-2 : 120
Main : Number of CompleteTasks : 2
Main : task 0 : true
Main : task 1 : true
Main : task 2 : false
Main : task 3 : false
Main : task 4 : false
Main : task 5 : false
Main : task 6 : false
Main : task 7 : false
Main : task 8 : false
Main : task 9 : false
pool-1-thread-2 : 2
pool-1-thread-2 : 2
Main : Number of CompleteTasks : 4
Main : task 0 : true
Main : task 1 : true
Main : task 2 : false
Main : task 3 : true
Main : task 4 : true
Main : task 5 : false
Main : task 6 : false
Main : task 7 : false
Main : task 8 : false
Main : task 9 : false
pool-1-thread-2 : 6
Main : Number of CompleteTasks : 6
Main : task 0 : true
Main : task 1 : true
Main : task 2 : false
Main : task 3 : true
Main : task 4 : true
Main : task 5 : true
Main : task 6 : true
Main : task 7 : false
Main : task 8 : false
Main : task 9 : false
pool-1-thread-1 : 40320
Main : Number of CompleteTasks : 7
Main : task 0 : true
Main : task 1 : true
Main : task 2 : true
Main : task 3 : true
Main : task 4 : true
Main : task 5 : true
Main : task 6 : true
Main : task 7 : false
Main : task 8 : false
Main : task 9 : false
pool-1-thread-2 : 720
Main : Number of CompleteTasks : 9
Main : task 0 : true
Main : task 1 : true
Main : task 2 : true
Main : task 3 : true
Main : task 4 : true
Main : task 5 : true
Main : task 6 : true
Main : task 7 : true
Main : task 8 : false
Main : task 9 : true
Main : Number of CompleteTasks : 9
Main : task 0 : true
Main : task 1 : true
Main : task 2 : true
Main : task 3 : true
Main : task 4 : true
Main : task 5 : true
Main : task 6 : true
Main : task 7 : true
Main : task 8 : false
Main : task 9 : true
pool-1-thread-1 : 362880
Main : Task 0 : 24
Main : Task 1 : 120
Main : Task 2 : 40320
Main : Task 3 : 2
Main : Task 4 : 2
Main : Task 5 : 6
Main : Task 6 : 1
Main : Task 7 : 720
Main : Task 8 : 362880
Main : Task 9 : 1
Future對象主要有一下兩個目的:
控制任務(wù)的狀態(tài):可以取消和檢查任務(wù)是否完成儡首。可以使用isDone檢查任務(wù)是否完成偏友,檢查isCancel檢查任務(wù)是否暫停蔬胯,也可以直接調(diào)用cancle方法暫停任務(wù)。
通過call方法獲取返回結(jié)果位他,為了達到這個目的氛濒,可以使用get方法,這個方法會一直等到callable對象的call方法返回結(jié)果鹅髓。如果此時任務(wù)尚未完成舞竿,get方法就會一直阻塞到線程完成。
** Future對象是用來管理Callavle任務(wù)的窿冯!**