Callable
Callable和Runnable对比
Callable表示有返回值的任务,Runnable表示没有返回值的任务。Thread构造方法只能直接接收Runnable,所以Callable通常需要先包装成FutureTask,再交给Thread执行。



- Callable是
java.util.concurrent包下的接口,有返回值,可以抛出被检查异常。 - Runnable是
java.lang包下的接口,没有返回值,不能直接抛出被检查异常。 - 二者调用的方法不同:
Runnable执行run(),Callable执行call()。
FutureTask实现了RunnableFuture接口,而RunnableFuture又继承了Runnable,所以Thread可以接收FutureTask对象。
java
new Thread(new Runnable()).start(); //创建一个线程去执行一个没有返回值的任务。
new Thread(new FutureTask<V>()).start(); //FutureTask实现了RunnableFuture接口,而RunnableFuture又继承了Runnable。所以Thread觉得它是Runnable,就接收了它。
new Thread(new FutureTask<V>(Callable)).start();代码测试
java
package com.mystpet.Callable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread thread = new MyThread();
FutureTask<Integer> futureTask = new FutureTask<>(thread);
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start();
Integer integer=futureTask.get();
System.out.println(integer);
}
}
class MyThread implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("call");
return 1024;
}
}运行结果:

A与B共用的是同一个futureTask对象。
缓存机制:
FutureTask内部维护了一个state(状态机)。只执行一次:当线程A拿到
futureTask并成功调用了call()方法后,FutureTask会将状态从NEW更新为COMPLETING,最后变为NORMAL(完成)。结果复用:当线程B启动时,它会检查
futureTask的状态。发现任务已经执行过或正在执行,它就不会再重复调用call()方法,而是直接等待结果。
细节
1、有缓存
2、结果可能需要等待,会阻塞!