Callable接口类似于Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。
但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。
如果想在线程执行完毕之后获取一个结果,那么Callable接口是一个选择
与Runnable不同,这个接口开始于JDK5

泛型类型

通过API观察这个接口可以发现,该接口后带了一个泛型
这个泛型指定的是返回值的类型

方法

1
V call() throws Exception//计算结果,如果无法计算则抛出异常
由于版本靠后,Thread类没有关于它的构造方法.
但是ExecutorService的submit方法有这个类型
以下是简单的案例 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
Future<Integer>[] futures = new Future[2];
for (int i = 0;i < 2;i++)
futures[i] = pool.submit(new MyCallable((i+1)*100));
for (int i = 0;i<futures.length;i++) {
try {
Integer result = futures[i].get();
System.out.println(result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
class MyCallable implements Callable<Integer>{
private int number;
public MyCallable(){}
public MyCallable(int number){this.number = number;}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1;i <= number;i++){
sum += i;
}
return sum;
}
}
由于返回的结果是Future接口类型,详情参见下一节
执行结果如下,可以看出得到了返回值

Future接口

方法

1
2
3
4
5
6
7
8
boolean cancel(boolean mayInterruptIfRunning)//取消此任务的执行
V get()throws InterruptedException, ExecutionException//等待计算完成并获取结果
V get(long timeout,TimeUnit unit)//设置计算完成的等待时间,超过报超时异常
throws InterruptedException,
ExecutionException,
TimeoutException
boolean isCancelled()//在任务完成前取消,返回true
boolean isDone()//如果任务完成,返回true
简单的测试案例 :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(2);
Futur9e<Integer> future = pool.submit(new MyCallable(10));
// future.cancel(true);
/*try {
System.out.println(future.get(1000,TimeUnit.MILLISECONDS));
} catch (Exception e) {
e.printStackTrace();
}*/
System.out.println(future.isCancelled());
System.out.println(future.isDone());

}
class MyCallable implements Callable<Integer>{
private int number;
public MyCallable(){}
public MyCallable(int number){this.number = number;}
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1;i <= number;i++){
sum += i;
Thread.sleep(100);
}
return sum;
}
}
首先是直接测试两个判断,返回的都是false
由于未取消任务,第一个false;由于main执行到isDone线程未执行结束,第二个false;
以下是执行结果 :

打开指定1000ms以内获取执行结果,此时若完成了任务,isDone为true
我这里得到了结果,执行结果如下 :

设置超时时间变小,会得到超时的异常。但是异常不属于取消任务,第一个仍为false
我这里设置的是995ms,其实有个问题,那就是执行应该使用1000ms 为什么到995才异常
但是异常结束也算是完成,第二个为true
执行结果如下 :

最后将cancel方法打开,不管设置true还是false;get方法都会异常
都会抛出CancellationException撤销异常
执行结果如下 :