除了Runnable,executor还支持另一种类型的任务Callable
Callable也是类似于Runnable的函数接口,不同之处在于Callable返回一个值
Callable也可以像Runnable一样提交给executorService,但是Callable的返回结果怎么办?因为submit()不会等待任务完成,executorService不能直接返回Callable结果。不过,executor可以返回一个Future类型的结果,它可以在稍后某个时间取出实际结果。
任何future()的调用都会造成阻塞,然后等待到Callable任务结束,在最糟糕的情况下,Callable任务持续执行,程序将没有响应,我们可以简单的传入一个时长来避免这种情况:
Integer result=future.get(1,TimeUnit.SECONDS);
Executors支持通过invokeAll()一次批量提交多个Callable。这个方法结果为一个Callable集合,返回一个future的列表。
批量提交Callable的另一种方式就是invokeAny(),它的工作方式与invokeAll稍有不同。在等待future对象的过程中,这个方法将会阻塞直到第一个Callable终止然后返回这一个Callable的结果。
package com.test.callable;
import java.util.concurrent.Callable;
/**
* 适用于包含返回值的线程
* @author Administrator
*
*/
public class AddCallable implements Callable<Integer>{
private int[] arr;
public AddCallable(int[] arr) {
super();
this.arr = arr;
}
@Override
public Integer call() throws Exception {
int sum = 0;
for(int i : arr) {
Thread.sleep(1000);
sum += i;
}
return new Integer(sum);
}
public int[] getArr() {
return arr;
}
public void setArr(int[] arr) {
this.arr = arr;
}
}
package com.test.callable;
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;
import java.util.concurrent.TimeUnit;
public class CallableTest {
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 10};
int[] arr2 = {1, 2, 3, 4, 5, 6, 7, 8, 10};
// 创建一个固定线程对象的线程池
ExecutorService service = Executors.newFixedThreadPool(2);
Future<Integer> future1 = service.submit(new AddCallable(arr1)); // 提交Callable任务
Future<Integer> future2 = service.submit(new AddCallable(arr2)); // 提交Callable任务
try {
//阻塞式方法 会等Callable中的任务执行完成之后 执行该代码
// 输出运算结果
System.out.println(future1.get()+future2.get());
service.shutdown(); // 退出程序
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}