Callable是一个函数式接口,和Runnable类似,代表一个线程的任务。与Runnable不同的是,Callable提供泛型返回值和可抛出Exception。
@FunctionalInterface
interface Callable<V> {
V call() throws Exception;
}
Future是异步计算结果接口。提供的接口确认异步执行是否完成,获取执行结果等。
interface Future<V> {
boolean isDone();
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
使用Callable实现线程:
FutureTask<Object> task = new FutureTask<>(new CallableDemo());
new Thread(task).start();
try {
task.get();
} catch (InterruptedException e) {
System.out.println("???");
e.printStackTrace();
} catch (ExecutionException e) {
System.out.println("!!!");
e.printStackTrace();
}
FutureTask类实现了Runnable接口和Future接口,并且依赖一个Callable实例。
class FutureTask<V> implements RunnableFuture<V> {
private Callable<V> callable; //callable实例
private Object outcome; //线程执行的结果或异常
private volatile int state; //线程执行状态
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
}
线程启动后执行的就是FutureTask的run方法,可以看到在run方法中调用了callable
的call(),异常或正确执行setException(ex) set(result)都会原子的把值赋给outcome属性。
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
private V report(int s) throws ExecutionException {
Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
对于callable的异常捕获要在get()方法外进行。因为FutureTask线程运行也是通过run()来执行,把callable跑出来的异常捕获了存在outcome属性中,然后在get()阶段再往上抛。
网友评论