Callable 接口类似于 Runnable
,两者都是为那些其实例可能被另一个线程执行的类设计的。但是Runnable 不会返回结果,并且无法抛出经过检查的异常;Callable可以返回结
果,并且能抛出异常。
Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,计算完成前get方法将被
阻塞。也可以在计算完成前取消等待,使用 cancel 方法,它有一个boolean类型的参数,true是以中断线程运行的方式取消,false是非中断方式取消。当取消等待时,继续使
用task.get()则会抛出异常,建议调用get方法之前,使用isCanceled方法判断一下再调用。
下面是具体的例子:
1)不取消的情况
package com.mythread.test;
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;
public class TestFutureThread {
public static void main(String args[]) {
System.out.println("start main thread");
ExecutorService exec = Executors.newCachedThreadPool();
Future<String> task = exec.submit(new TestFuture());
try {
Thread.sleep(1000 * 2);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("main thread get value");
// task.cancel(false);
try {
if (!task.isCancelled()) {
System.out.println(task.get());
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
exec.shutdown();
System.out.println("end main thread");
}
}
class TestFuture implements Callable<String> {
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
System.out.println(" start new thread.");
Thread.sleep(1000 * 5);
System.out.println(" end new thread.");
return "return value";
}
}
运行结果:
start main thread
start new thread.
main thread get value
end new thread.
return value
end main thread
从这个结果可以看出,task.get方法是阻塞的,直到线程执行完成返回结果,主线程才返回。
2)取消的情况,非中断
将例子1,去掉注释
// task.cancel(false);
返回结果:
start main thread
start new thread.
main thread get value
end main thread
end new thread.
从这个结果可以看出,task.get方法没有阻塞,主线程先结束。
3)取消的情况,中断
将例子1,去掉注释,并将false改为true
// task.cancel(false);
start main thread
start new thread.
main thread get value
end main thread
从这个结果可以看出,task.get方法没有阻塞,主线程结束,但task线程没有结束,而是直接中断了。